Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
СиАОД_Тычинина.docx
Скачиваний:
1
Добавлен:
01.07.2025
Размер:
2 Мб
Скачать
☆
  1. Таблица 1. 2

  2. Варианты задания

Вариант

Задание

1

;

.

2

;

.

3

.

4

.

5

6

7

.

8

.

9

10

.

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

  1. Что такое интегрированная среда разработки?

  2. Для чего в интегрированной среде Visual С++ служит окно редактора?

  3. Для чего в интегрированной среде Visual С++ служит окно вывода?

  4. Что такое директива препроцессора?

  5. Назовите операцию помещения в поток.

  6. Назовите операцию извлечения из потока.

  7. Что такое пространство имен?

  8. Что такое функция?

  9. Для чего служит команда return?

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

  11. Для чего нужна функция main?

  12. Для чего в задаче 1 целое число 5 представляют в формате 5.0?

  13. Что необходимо сделать для использования библиотеки математических функций С++?

  14. Какая функция используется для возведения числа в степень?

  15. Какая функция возвращает модуль числа?

  16. Какая функция вычисляет квадратный корень?

Лабораторная работа №2. Базовые структуры алгоритмов.

Цель работы

Приобретение навыков работы с операторами ветвления и цикла.

Теоретическая часть

Базовые конструкции структурного программирования [1, 2]

Следование, ветвление и цикл называют базовыми конструкциями структурного программирования. Следованием называется конструкция, представляющая собой последовательное выполнение двух или более операторов (простых или составных). Ветвление задает выполнение либо одного, либо другого оператора, в зависимости от выполнения какого-либо условия. Цикл задает многократное выполнение оператора (рисунок 2.1).

Рисунок 2.1

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

Целью использования базовых конструкций является получение программы простой структуры. Такую программу легко читать (а программы чаще приходится читать, чем писать), отлаживать и при необходимости вносить в нее изменения. В большинстве языков высокого уровня существует несколько реализаций базовых конструкций; в C++ есть три вида циклов и два вида ветвлений (на два и на произвольное количество направлений). Они введены для удобства программирования, и в каждом случае надо выбирать наиболее подходящие средства. Рассмотрим операторы языка, реализующие базовые конструкции структурного программирования.

Оператор «выражение»

Любое выражение, завершающееся точкой с запятой, рассматривается как оператор, выполнение которого заключается в вычислении выражения. Частным случаем выражения является пустой оператор ; (он используется, когда по синтаксису оператор требуется, а по смыслу – нет). Примеры:

i++; // выполняется операция инкремента

а* = b + с; // выполняется умножение с присваиванием

fun(i, к); // выполняется вызов функции

Операторы ветвления

Условный оператор if

Условный оператор if используется для разветвления процесса вычислений на два направления. Структурная схема оператора приведена на рисунке 2.1.

Формат оператора:

if ( выражение ) оператор_1; [else оператор_2;]

В квадратных скобках указана необязательная часть.

Рисунок 2.1

Сначала вычисляется выражение, которое может иметь арифметический тип или тип указателя. Если оно не равно нулю (имеет значение true), выполняется первый оператор, иначе – второй. После этого управление передается на оператор, следующий за условным. Одна из ветвей может отсутствовать, логичнее опускать вторую ветвь вместе с ключевым словом else. Если в какой-либо ветви требуется выполнить несколько операторов, их необходимо заключить в блок (блок ограничивается фигурными скобками), иначе компилятор не сможет понять, где заканчивается ветвление. Блок может содержать любые операторы, в том числе описания и другие условные операторы (но не может состоять из одних описаний). Необходимо учитывать, что переменная, описанная в блоке, вне блока не существует.

Примеры:

if (а<0) b = 1; //1

if (a<b && (a>d || a==0)) b++; else {b *= a; a = 0;} //2

if (a<b) { if (a<c) m = a; else m = c;} else { if (b<c) m = b; else m = c;} // 3

if (a++) b++; // 4

if (b>a) max = b; else max = a; //5

В примере 1 отсутствует ветвь else. Подобная конструкция называется «пропуск оператора», поскольку присваивание либо выполняется, либо пропускается, в зависимости от выполнения условия. Если требуется проверить несколько условий, их объединяют знаками логических операций. Например, выражение в примере 2 будет истинно в том случае, если выполнятся одновременно условие а<b и одно из условий в скобках. Если опустить внутренние скобки, будет выполнено сначала логическое И, а потом – ИЛИ.

Оператор в примере 3 вычисляет наименьшее значение из трех переменных. Фигурные скобки в данном случае не обязательны, так как компилятор относит часть else к ближайшему if.

Пример 4 напоминает о том, что хотя в качестве выражений в операторе if чаще всего используются операции отношения, это не обязательно. Конструкции, подобные оператору в примере 5, проще и нагляднее записывать в виде условной операции (в данном случае: max = (b > а) ? b : а;).

Задача 2.1. Производится выстрел по мишени, изображенной на рисунке 2.2. Определить количество очков.

Рисунок 2.2

Программа на языке C++:

#include <iostream>

using namespace std;

int main() {

setlocale(LC_CTYPE,"RUS");

float x, у;

int kol;

cout<<"Введите координаты выстрела"<<endl;

cin>>x>>у;

if ( x*x + y*y < 1 ) kol = 2;

else if( x*x + y*y < 4 ) kol = 1;

else коl = 0;

cout<<endl<<"Очков: " <<kol;

return 0;

}

Распространенная ошибка при записи условных операторов – использование в выражениях вместо проверки на равенство (= = простого присваивания (=), например, if(a=1) b=0.

Синтаксической ошибки нет, так как операция присваивания формирует результат, который и оценивается на равенство/неравенство нулю. В данном примере присваивание переменной b будет выполнено независимо от значения переменной а. Поэтому в выражениях проверки переменной на равенство константе константу рекомендуется записывать слева от операции сравнения: «if (1==а) b=0;».

Вторая ошибка – неверная запись проверки на принадлежность диапазону. Например, чтобы проверить условие 0<х<1, нельзя записать его в условном операторе непосредственно, так как будет выполнено сначала сравнение 0<х, а его результат (true или false, преобразованное в int) будет сравниваться с 1. Правильный способ записи: if(0<x && х<1).

Тип переменных выбирается исходя из их назначения. Координаты выстрела нельзя представить целыми величинами, так как это приведет к потере точности результата, а счетчик очков не имеет смысла описывать как вещественный. Даже такую простую программу можно еще упростить с помощью промежуточной переменной и записи условия в виде двух последовательных, а не вложенных, операторов if (обратите внимание, что в первом варианте значение переменной kol присваивается ровно один раз, а во втором – от одного до трех раз в зависимости от выполнения условий):

#include <iostream>

using namespace std;

int main() {

setlocale(LC_CTYPE,"RUS");

float x, у, temp;

int kol;

cout<<"Введите координаты выстрела"<<endl;

cin>>x>>у;

temp = x*x+y*y;

kol=0;

if (temp < 4 ) kоl = 1;

if (temp < 1 ) kol = 2;

cout<<endl<<"Очков: " <<kol;

return 0;

}

Если какая-либо переменная используется только внутри условного оператора, рекомендуется объявить ее внутри скобок, например:

if (int i = fun(t)) a -=i; else a +=i;

Объявление переменной в тот момент, когда она требуется, то есть когда ей необходимо присвоить значение, является признаком хорошего стиля и позволяет избежать случайного использования переменной до ее инициализации. Объявлять внутри оператора if можно только одну переменную. Область ее видимости начинается в точке объявления и включает обе ветви оператора.

Оператор switch

Оператор switch (переключатель) предназначен для разветвления процесса вычислений на несколько направлений. Формат оператора:

switch ( выражение ){

case константное_выражение_1: [список_операторов_1]

case константное_выражение_2: [список_операторов_2]

…

case константное_выражение_n: [список_операторов_n]

[default: операторы ]

}

Структурная схема оператора приведена на рисунке 2.3.

Рисунок 2.3

Выполнение оператора начинается с вычисления выражения (оно должно быть целочисленным), а затем управление передается первому оператору из списка, помеченного константным выражением, значение которого совпало с вычисленным. После этого, если выход из переключателя явно не указан, последовательно выполняются все остальные ветви. Выход из переключателя обычно выполняется с помощью операторов break или return. Оператор break выполняет выход из самого внутреннего из объемлющих его операторов switch, for, while и do. Оператор return выполняет выход из функции, в теле которой он записан.

Все константные выражения должны иметь разные значения, но быть одного и того же целочисленного типа. Несколько меток могут следовать подряд. Если совпадения не произошло, выполняются операторы, расположенные после слова default (а при его отсутствии управление передается следующему за switch оператору).

Задача 2.2. Написать программу, реализующую простейший калькулятор на 4 действия.

#include <iostream>

using namespace std;

int main() {

setlocale(LC_CTYPE,"RUS");

int a, b,res;

char op;

cout<<"Введите 1-й операнд: "<<endl; cin>>a;

cout<<"Введите знак операции: "<<endl; cin>>op;

cout<<"Введите 2-й операнд: "<<endl; cin>>b;

bool f = true;

switch (op) {

case '+': res=a+b; break;

case '-': res=a-b; break;

case '*': res=a*b; break;

case '/': res=a/b; break;

default: cout<<" Неизвестная операция ";

f=false;

}

if (f) cout<<" Результат: "<<res;

return 0;

}

Операторы цикла

Операторы цикла используются для организации многократно повторяющихся вычислений. Любой цикл состоит из тела цикла, то есть тех операторов, которые выполняются несколько раз, начальных установок, модификации параметра цикла и проверки условия продолжения выполнения цикла. Один проход цикла называется итерацией. Проверка условия выполняется на каждой итерации либо до тела цикла (тогда говорят о цикле с предусловием), либо после тела цикла (цикл с постусловием). Разница между ними состоит в том, что тело цикла с постусловием всегда выполняется хотя бы один раз, после чего проверяется, надо ли его выполнять еще раз (рисунок 2.4). Проверка необходимости выполнения цикла с предусловием делается до тела цикла, поэтому возможно, что он не выполнится ни разу. Переменные, изменяющиеся в теле цикла и используемые при проверке условия продолжения, называются параметрами цикла. Целочисленные параметры цикла, изменяющиеся с постоянным шагом на каждой итерации, называются счетчиками цикла.

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

Цикл завершается, если условие его продолжения не выполняется. Возможно принудительное завершение как текущей итерации, так и цикла в целом. Для этого служат операторы break, continue, return и goto. Передавать управление извне внутрь цикла не рекомендуется. Для удобства в C++ есть три разных оператора цикла – while, do while и for.

Рисунок 2.4. Структурные схемы операторов цикла:

а – цикл с предусловием; б – цикл с постусловием

Цикл с предусловием (while)

Цикл с предусловием имеет вид

while ( выражение ) оператор;

Выражение определяет условие повторения тела цикла, представленного простым или составным оператором. Выполнение оператора начинается с вычисления выражения. Если оно истинно (не равно false), выполняется оператор цикла. Если при первой проверке выражение равно false, цикл не выполнится ни разу. Тип выражения должен быть арифметическим или приводимым к нему. Выражение вычисляется перед каждой итерацией цикла.

Задача 2.3. Написать программу, печатающую таблицу значений функции y=х2+1 во введенном диапазоне

#include <iostream>

using namespace std;

int main() {

setlocale(LC_CTYPE,"RUS");

float Xn, Xk, Dx;

cout<< "Введите диапазон и шаг изменения аргумента: ";

cin>>Xn, Xk, Dx;

cout<<" | X | Y |"<<endl; // шапка таблицы

float X = Xn; // установка параметра цикла

while (X <= Хк) { // проверка условия продолжения

cout<<" | | | "<< (X, X*X + 1 ) ; // тело цикла

X += Dx; // модификация параметра

}

return 0;

}

Задача 2.4. Написать программу, которая находит все делители целого положительного числа:

#include <iostream>

using namespace std;

int main() {

setlocale(LC_CTYPE,"RUS");

int num;

cout<<" Введите число : "; cin>>num;

int half = num/2; // половина числа

int div = 2; // кандидат на делитель

while (div <= half) {

if (!(num % div)) cout<<div<<endl;

div++;

}

return 0;

}

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

while (int х = 0) { ... / * область действия х */ }

Цикл с постусловием (do while)

do оператор while выражение;

Сначала выполняется простой или составной оператор, составляющий тело цикла, а затем вычисляется выражение. Если оно истинно (не равно fаlse), тело цикла выполняется еще раз. Цикл завершается, когда выражение станет равным false или в теле цикла будет выполнен какой-либо оператор передачи управления. Тип выражения должен быть арифметическим или приводимым к нему.

Задача 2.5. Написать программу, вычисляющую квадратный корень вещественного аргумента X с заданной точностью Eps по итерационной формуле: yn =1/2 (уn-1 + x/yn-1), где yn-1 – предыдущее приближение к корню (в начале вычислений выбирается произвольно), yn – последующее приближение. Процесс вычислений прекращается, когда приближения станут отличаться друг от друга по абсолютной величине менее чем на величину заданной точности. Для вычисления абсолютной величины используется стандартная функция fabs(), объявление которой находится в заголовочном файле <math.h>.

#include <iostream>

using namespace std;

#include <math.h>

int main() {

setlocale(LC_CTYPE,"RUS");

double X, Eps; // аргумент и точность

double Yp, Y = 1; // предыдущее и последующее приближение

cout<<" Введите аргумент и точность: "<<endl;

cin>>X, Eps;

do{

Yp = Y;

Y = (Yp + X/Yp)/2;

}

while (fabs(Y - Yp) >= Eps);

cout<<" Kopeнь из X= "<< Y;

return 0;

}

Цикл с параметром (for)

Цикл с параметром имеет следующий формат:

for (инициализация; выражение; модификации) оператор;

Инициализация используется для объявления и присвоения начальных значений величинам, используемым в цикле. В этой части можно записать несколько операторов, разделенных запятой (операцией «последовательное выполнение»), например, так:

for (int i = 0, j = 2; ...

int к. m;

for (k = 1, m = 0; ...

Областью действия переменных, объявленных в части инициализации цикла, является цикл. Инициализация выполняется один раз в начале исполнения цикла. Выражение определяет условие выполнения цикла: если его результат, приведенный к типу bool, равен true, цикл выполняется. Цикл с параметром реализован как цикл с предусловием.

Модификации выполняются после каждой итерации цикла и служат обычно для изменения параметров цикла. В части модификаций можно записать несколько операторов через запятую. Простой или составной оператор представляет собой тело цикла. Любая из частей оператора for может быть опущена, но точки с запятой необходимо оставить на своих местах.

Пример (оператор, вычисляющий сумму чисел от 1 до 100):

for (int i = 1, s = 0; i<=100; i++) s += i;

Задача 2.6. Решить задачу 2.3 с использованием цикла с параметром.

#include <iostream>

using namespace std;

int main() {

setlocale(LC_CTYPE,"RUS");

float Xn, Xk, Dx, X;

cout<<"Введите диапазон и шаг изменения аргумента: " <<endl;

cin>>Хn, Хк, Dx;

cout<<"| X| Y|"<<endl;

for (X = Xn; X<=Xk; X+= Dx)

cout<<"| | |"<<endl<< X, X*X + 1;

return 0;

}

Задача 2.7. Решить задачу 2.4 с использованием цикла с параметром.

#include <iostream>

using namespace std;

int main() {

setlocale(LC_CTYPE,"RUS");

int num, half, div;

cout<<" Введите число : "; cin>>num;

for (half = num / 2, div = 2; div <= half; div++)

if (!(num % div))cout « div «endl;

return 0;

}

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

Операторы цикла взаимозаменяемы, но можно привести некоторые рекомендации по выбору подходящего в каждом конкретном случае.

Оператор do while обычно используют, когда обязательно требуется выполнить цикл хотя бы раз (например, если в цикле производится ввод данных).

Оператором while удобнее пользоваться в случаях, когда число итераций заранее не известно, очевидных параметров цикла нет или модификацию параметров удобнее записывать не в конце тела цикла.

Оператор for предпочтительнее в большинстве остальных случаев (однозначно – для организации циклов со счетчиками).

Порядок выполнения работы

  1. Ознакомьтесь с теоретическим материалом и в соответствии с ним создайте новый проект.

  2. Разберите все задачи теоретической части и проверьте их работоспособность в Visual C++.

  3. Сделайте задание для самостоятельного выполнения в соответствии с номером варианта.

  4. Напишите отчет в соответствии с требованиями, приведенными на стр. 20.

  5. Потренируйтесь отвечать на контрольные вопросы.

Задание для самостоятельного выполнения

  1. Разветвляющиеся программы

Вычислить и вывести на экран в виде таблицы значения функции F на интервале от Хнач до Хкон с шагом dX; а, b, с – действительные числа в соответствие с номером варианта (таблила 2.1). Значения а, b, с, Хнач, Хкон, dX ввести с клавиатуры.

Таблица 2.1