Федеральное государственное бюджетное образовательное учреждение высшего профессионального образования «Адыгейский государственный университет» Инженерно-физический факультет Кафедра автоматизированных систем обработки информации и управления Довгаль В.А, Коробков В.Н. Программирование на языке С++ в среде Microsoft Visual Studio (Часть 1) Учебно - методическое пособие Майкоп 2015 УДК 004.43 (075.8) ББК 32.973-018.1я73 Д 58 Печатается по решению редакционно-издательского совета Адыгейского государственного университета Рецензенты: Чефранов С.Г., д.э.н., доцент, заведующий кафедрой информационной безопасности и прикладной информатики ФГБОУ ВПО «Майкопский государственный технологический университет». Бучацкая В.В, доцент кафедры прикладной математики и информационных технологий ФГБОУ ВПО «АГУ», к.т.н., доцент. Довгаль В.А., Коробков В.Н. Д 58 Программирование на языке С++ в среде Microsoft Visual Studio (Часть 1): учебно - методическое пособие. – Майкоп: Издательство: АГУ, 2015. – 62 с. Учебно-методическое пособие предназначено для студентов, изучающих дисциплину «Программирование» направления подготовки 09.03.01 – «Информатика и вычислительная техника», профиль «Автоматизированные системы обработки информации и управления», и дисциплину «Программирование и основы алгоритмизации» направления подготовки 27.03.04 – «Управление в технических системах», профиль «Управление и информатика в технических системах». Пособие так же может использоваться студентами других специальностей и направлений. Учебно-методическое пособие посвящено введению в основы алгоритмизации и программирования на языке С++ в среде программирования Microsoft Visual Studio 2010. Пособие подготовлено на кафедре автоматизированных систем обработки информации и управления инженерно-физического факультета ФГБОУ ВПО «Адыгейский государственный университет». © Адыгейский государственный университет, 2015 СОДЕРЖАНИЕ Введение....................................................................................................................................................... 4 Лабораторная работа №1 Программирование линейных алгоритмов .................................................. 5 Лабораторная работа №2 Программирование разветвляющихся алгоритмов ................................... 15 Лабораторная работа № 3 Программирование структур ветвления с применением оператора множественной выборки ......................................................................................................................... 23 Лабораторная работа №4 Программирование циклических алгоритмов ........................................... 31 Лабораторная работа №5 Структурированный тип данных - массив ................................................. 38 Лабораторная работа №6 Методы сортировки массива ....................................................................... 47 Лабораторная работа № 7 Обработка символьной информации, работа со строками ...................... 53 Рекомендуемая литература....................................................................................................................... 62 Введение Целью пособия является предоставление обучающимся теоретических и практических основ составления алгоритмов решения задач и программирования на языке С++. Учебно-методическое пособие предназначено для проведения лабораторных работ по языку С++ в среде программирования Microsoft Visual Studio 2010. Основными задачами лабораторных работ являются: закрепление знаний, полученных на лекционных занятиях по дисциплине «Программирование и основы алгоритмизации»; развитие у студентов практических навыков создания алгоритмов и реализации их на языке С++; получение навыков работы в среде программирования Microsoft Visual Studio 2010. В результате выполнения лабораторных работ, обучающиеся должны приобрести знания в области разработки алгоритмов решения задач и основ программирования на языке С++. Материал адаптирован к использованию с применением модульно-рейтинговой системы оценки успеваемости студентов. В конце каждой лабораторной работы представлены задачи для индивидуального решения. Первые пять задач могут быть решены коллективно, и еще две задачи выполняются индивидуально, согласно выданному варианту. Лабораторная работа №1 Программирование линейных алгоритмов Цель работы: выработать практические навыки работы с системой Microsoft Visual Studio, научиться создавать, вводить в компьютер, выполнять и исправлять простейшие программы на языке Си в режиме диалога, познакомиться с диагностическими сообщениями компилятора об ошибках при выполнении программ, реализующих линейные алгоритмы. Общие сведения: Алгоритм называется линейным, если результат решения задачи получается путем однократного выполнения заданного набора операторов не зависимо от исходных данных. Операторы выполняются в той последовательности, в которой они расположены в программе. Проиллюстрируем это с помощью математического примера. Пример1: Определить расстояние на плоскости между двумя точками с заданными координатами M1(x1,y1) и M2(x2,y2) Этапы решения задачи: 1. Математическая модель: расстояние на плоскости между двумя точками M1(x1,y1) и M2(x2,y2) высчитывается по формуле 2. На рисунке 1.1 представлена схема алгоритма. Рис. 1.1. Схема алгоритма рассматриваемой задачи Уточним содержимое блока «Вычисление и печать расстояния». Рис. 1.2. Схема алгоритма блока «Вычисление и печать расстояния» Дальнейшая детализация не требуется. Затем необходимо перевести блок-схему на язык С++. Для этого необходимо познакомиться со структурой программы на языке С++. Программа состоит из директив препроцессора и отдельных модулей, которые называются подпрограммами или функциями. В общем виде структура программы может быть представлена в таком виде: 1. Комментарий, описывающий назначение программы, ее версию и т.д. Например: /*Это моя первая программа на языке С*/ 2. Директива препроцессора. Например, для подключения библиотек стандартных функции пользователя используется директива препроцессора #include, форма записи которого приведена в примере ниже. Для замены числовых и текстовых констант буквенными обозначениями применяется директива препроцессора #define. Для совместимости со старыми версиями языка С используется директива using namespace std; задающая стандартную библиотеку std. В этом случае вместо указания пространства имен можно стандартную библиотеку не задавать. 3. Объявления глобальных переменных и прототипов функции. 4. Главный модуль программы. 5. Функции, уникальные для данного приложения. Простейшая программа на языке С состоит всего из 8 символов: main(){ } Основная программа всегда называется именем main. Внимание: в языке программирования Си большие и маленькие буквы различаются и все стандартные операторы Си записываются маленькими буквами. Пустые круглые скобки означают, что функция main не имеет аргументов. Фигурные скобки обозначают начало и конец функция main. Отсутствие внутри фигурных скобок каких-либо операторов означает, что программа ничего не выполняет. Она просто соответствует правилам языка Си, ее можно скомпилировать и получить исполняемый файл с расширением exe. Между фигурными скобками располагаются операторы, реализующие вышеприведенный алгоритм: #include <iostream> using namespace std; #include <conio.h> #include <math.h> int main(void) { int x1, x2, y1, y2; float d; cout<<"x1="; cin>>x1; cout<<"y1="; cin>>y1; cout<<"x2="; cin>>x2; cout<<"y2="; cin>>y2; d=sqrt(float (x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)); cout<<"d="; cout<<d; _getch(); return 0; } Вначале к тексту программы подключаются так называемые заголовочные (h от header – заголовок) файлы системы (include – включить). В этих файлах описаны системные функции и их аргументы. Используя эти описания, компилятор проверяет правильность вызова системных функций. В нашем случае программа использует системные функции ввода ( cin>> ) и вывода ( cout<< ), описания которых находятся в заголовочном файле с именем iostream.h, а также функцию ожидания нажатия какой-либо клавиши ( getch ), описание которой находится в заголовочном файле conio.h. Затем идет заголовок функции main. Функция с таким названием обязана присутствовать в каждой программе на языке C, C++. Именно с нее начинается выполнение программы, она – главная (именно так переводится служебное слово main ). Предшествующее ей служебное слово int (от integer – целый) сообщает, что результатом работы функции main должно быть целое число. По возвращаемому функцией значению операционная система, запустившая программу main, может «сообразить», правильно или неправильно завершилась работа программы. По общепринятому соглашению нулевое значение, возвращаемое функцией main, свидетельствует о нормальном завершении работы программы. Служебное слово void (дословно – пустота), указанное в круглых скобках, сообщает, что у функции main аргументы отсутствуют. Четыре переменные x1, x2, y1 и y2, объявленные в программе, имеют тип int, означающий, что переменные могут принимать только целочисленные значения. Далее следует блок операторов, позволяющих вводить значения этих переменных с клавиатуры. На основании введенных значений производится расчет значения переменной d. Следующим шагом является вывод на экран монитора двух сообщений – текстовое строки ( d= ) и числового значения переменной d . Функция _getch используется в программе для задержки на экране выводимого сообщения до тех пор, пока не будет нажата какая-нибудь клавиша ( getch – от get character, дай символ). Последняя выполняемая строка return 0 сообщает, что функция main завершается с нулевым результатом и управление передается операционной системе. Осталось реализовать программу с помощью средства разработки. Реализация программы: На современном уровне все этапы создания, трансляции, компоновки, отладки и проверки программы объединены и выполняются внутри специальной программыоболочки, которую называют интегрированная среда разработки (IDE – integrated development environment). В нее входят: редактор текста; транслятор; компоновщик; отладчик. В этой среде достаточно набрать текст программы и нажать на одну клавишу, чтобы она выполнилась (если нет ошибок). Если в программе есть ошибки, вы увидите в нижней части экрана оболочки сообщения об этих ошибках (к сожалению, на английском языке). Если щелкнуть по одной из этих строчек, в тексте программы выделяется строка, в которой транслятору чтото не понравилось. При поиске ошибок надо помнить, что часто ошибка сделана не в выделенной строке, а в предыдущей – проверяйте и ее тоже; часто одна ошибка вызывает еще несколько, и появляются так называемые наведенные ошибки. В качестве инструментальной среды для написания программ в данном учебнометодическом пособии рассматривается среда разработки Microsoft Visual Studio 2010. В результате запуска среды, появляется стартовая страница, представленная на рисунке 1.3. Следующим шагом является создание нового проекта: в меню Файл необходимо выбрать Создать – Проект (или комбинацию клавиш Ctrl + Shift + N ). Результат выбора пунктов меню для создания нового проекта показан на рис. 1.4. Рис. 1.3. Стартовая страница Visual Studio 2010 Рис. 1.4. Окно с выбором нового проекта Среда Visual Studio отобразит окно «Создать проект», в котором необходимо выбрать тип создаваемого проекта. Проект (project) используется в Visual Studio для логической группировки нескольких файлов, содержащих исходный код, на одном из поддерживаемых языков программирования, а также любых вспомогательных файлов. Обычно после сборки проекта (которая включает компиляцию всех входящих в проект файлов исходного кода) создается один исполняемый модуль. В окне «Создать проект» следует развернуть узел Visual С++, обратиться к пункту Win32 и на центральной панели выбрать «Консольное приложение Win32». Выбор этой опции показан на рис. рис. 1.5. Рис. 1.5. Выбор типа проекта Затем в поле редактора «Имя» (где по умолчанию имеется <Введите_имя>) следует ввести имя проекта, например, lab1. В поле «Расположение» можно указать путь размещения проекта, или выбрать путь размещения проекта с помощью клавиши (кнопки) «Обзор». По умолчанию проект сохраняется в специальной папке Projects. Пример выбора имени проекта показано на рис. 1.6. Рис. 1.6. Пример задания имени проекта Одновременно с созданием проекта Visual Studio создает решение. Решение (solution) – это способ объединения нескольких проектов для организации более удобной работы с ними. После нажатия кнопки «OK» откроется окно «Мастер приложений Win32» (мастер создания приложений для операционных систем Windows), показанное на рис. 1.7. Выбор имени проекта может быть достаточно произвольным: допустимо использовать числовое значение, допустимо имя задавать через буквы русского алфавита. В дальнейшем будем использовать имя, набранное с помощью букв латинского алфавита и, может быть, с добавлением цифр. Рис. 1.7. Мастер создания приложения На первой странице представлена информация о создаваемом проекте, на второй можно сделать первичные настройки проекта. После обращения к странице» Параметры приложения», или после нажатия кнопки» Далее» получим окно, показанное на рис. 1.8. Рис. 1.8. Страница мастера настройки проекта по умолчанию В дополнительных опциях («Дополнительные параметры») следует поставить галочку в поле «Пустой проект». Получим экранную форму, показанную на рис. 1.9. Здесь и далее будут создавать проекты по приведенной схеме, т.е. проекты в консольном приложении, которые должны создаваться целиком программистом (за счет выбора «Пустой проект»). После нажатия кнопки «Готово», получим экранную форму, показанную на рис. 1.10, где приведена последовательность действий добавления файла для создания исходного кода к проекту. Стандартный путь для этого: подвести курсор мыши к папке «Файлы исходного кода» из узла lab1 в левой части открытого проекта приложения, щелкнуть правой кнопкой мыши и выбрать команды контекстного меню «Добавить» и «Создать новый элемент». Рис. 1.9. Выполненная настройка мастера приложений Рис. 1.10. Меню добавления нового элемента к проекту После выбора (нажатия) «Создать новый элемент» получим окно, показанное на рис. 1.11, где через пункт меню «Код» узла Visual C++ выполнено обращение к центральной части панели, в которой осуществляется выбор типа файлов. В данном случае требуется обратиться к закладке «Файл C++ (.cpp)». Теперь в поле редактора «Имя» (в нижней части окна) следует задать имя нового файла (расширение можно не указывать). Например, main. Имя файла может быть достаточно произвольным, но имеется негласное соглашение, что имя файла должно отражать его назначение и логически описывать исходный код, который в нем содержится. В проекте, состоящем из нескольких файлов, имеет смысл выделить файл, содержащий главную функцию программы, с которой она начнет выполняться. В данном пособии такому файлу мы будем задавать имя main.cpp, где расширение «.сpp» указывает на то, что этот файл содержит исходный код на языке С++, и он будет транслироваться соответствующим компилятором. Программам на языке С принято давать расширение «.с». После задания имени файла в поле редактора «Имя», получим форму, показанную на рис. 1.12. Рис. 1.11. Окно выбора типа файла для подключения к проекту Рис. 1.12. Задание имени файла, подключаемому к проекту Затем следует нажать кнопку «Добавить». Вид среды Visual Studio после добавления первого файла к проекту показан на рис. 1.13. Добавленный файл отображается в дереве «Обозреватель решений» под узлом «Файлы исходного кода», и для него автоматически открывается редактор. На рис. 1.13 в левой панели в папке «Обозреватель решений» отображаются файлы, включенные в проект в папках. Приведем описание. Папка «Файлы исходного кода» предназначена для файлов с исходным кодом. В этой папке отображаются файлы с расширением .сpp. Папка «Заголовочные файлы» содержит заголовочные файлы с расширением .h. Папка «Файлы ресурсов» содержит файлы ресурсов, например изображения и т.д. Папка «Внешние зависимости» отображает файлы, не добавленные явно в проект, но использующиеся в файлах исходного кода, например включенные при помощи директивы #include. Обычно в папке «Внешние зависимости» присутствуют заголовочные файлы стандартной библиотеки, использующиеся в проекте. Справа в окне редактора наберем программу, приведенную выше. Затем необходимо запустить программу на выполнение, выбрав команды Отладка – Запуск без отладки (или комбинацию клавиш Ctrl + F5 ). Результат выбора пунктов меню для создания нового проекта показан на рис. 1.14. Рис. 1.13. Подключение файла проекта Рис. 1.14. Окно выполнения задачи. Задачи для индивидуального решения: 1. По двум данным катетам найти гипотенузу, периметр и площадь прямоугольного треугольника. 2. В треугольнике известны три стороны A,B и угол c, между ними; найти сторону C, углы a,b. 3. Вычислить объем цилиндра с радиусом основания r и высотой h. 4. Треугольник задан координатами своих вершин. Найти периметр и площадь треугольника. 5. По заданным сторонам прямоугольника вычислить его периметр, площадь и длину диагонали. Вариант 1 1. 2. Вариант 2 1. 2. Вариант 3 1. 2. Вариант 4 1. 2. Вариант 5 1. 2. Вариант 6 1. 2. Вариант 7 1. 2. Вариант 8 1. 2. Вариант 9 1. 2. Вариант 10 1. 2. Вычислить длину отрезка, зная координаты точек A и B. Три сопротивления R1, R2 и R3 соединены параллельно. Найти сопротивление соединения. Вычислите медианы треугольника, заданного сторонами a, b, c. Поменять между собой значения двух переменных X и Y используя только одну дополнительную переменную. Найти площадь кольца, внутренний и внешний радиус которого вводятся с клавиатуры. Определить расстояние, пройденное физическим телом за время t, если тело движется с постоянным ускорением а и имеет в начальный момент времени скорость V0. Вычислить количество часов, минут и секунд, прошедших с начала суток. Поменять местами значения переменных x=>y, y=>z, z=>x используя только одну дополнительную переменную. Вычислить высоту треугольника, опущенную на сторону а, по известным значениям длин его сторон a, b, c. Определить время падения камня на поверхность земли с высоты h. Найти площадь грани, площадь поверхности и объем куба, длина ребра которого вводится с клавиатуры. Ввести 4-значное число. Превратить его в 2-значное, отбросив первую и последнюю цифру. Задается длина окружности. Найти площадь круга и шара, ограниченного этой окружностью. Ввести два положительных числа a и b (a>b). Определить на сколько первое число больше второго и во сколько раз первое число больше второго. Угол а задан в градусах, минутах, секундах. Найти его величину в радианах. С клавиатуры вводится трехзначное целое число, поменять местами первую и последнюю цифры в числе. С клавиатуры задается число К, больше 99. Выбросить из записи К цифру, обозначающую сотни. Вывести полученное число на экран. Найти среднее арифметическое трех чисел, вводимых с клавиатуры Задается длина окружности. Найти площадь квадрата, вписанного в эту окружность. Найти среднее геометрическое трех чисел, вводимых с клавиатуры Лабораторная работа №2 Программирование разветвляющихся алгоритмов Цель работы: научиться правильно использовать условный оператор if; научиться составлять программы решения задач на разветвляющиеся алгоритмы. Общие сведения Алгоритм называется разветвляющимся, если последовательность шагов в нем определяется некоторым условием. Выполнение конкретной ветви алгоритма определяется входными данными задачи. Ветвление осуществляется с помощью оператора if, который имеет следующий формат: if (выражение) оператор-1; [else оператор-2;] Выполнение оператора if начинается с вычисления выражения. Далее работа этого оператора осуществляется по следующей схеме: если выражение истинно (т.е. отлично от нуля), то выполняется оператор-1; если выражение ложно (т.е. равно нулю),то выполняется оператор-2; если выражение ложно и отсутствует оператор-2 (в квадратные скобки заключена необязательная конструкция), то выполняется следующий за if оператор. Пример: if (i < j)i++; else {j = i-3; i++; } В данном примере показано, что на месте оператор-1, так же как и на месте оператор-2 могут находиться как простые, так и сложные конструкции. Если вторая часть оператора if отсутствует (else …), то оператор записан в неполной форме. Например: if (i < j)i++; Допускается использование вложенных операторов if. Для того, чтобы программа была более наглядной и удобной для чтения, целесообразно выделять операторы и конструкции во вложенных операторах if с помощью фигурных скобок (даже если они не требуются). При отсутствии фигурных скобок компилятор связывает каждое ключевое слово else с наиболее близким оператором if, для которого нет else. Примеры: if (t>b) { if (b < r) r=b; } else r=t; Если же в программе опустить фигурные скобки, стоящие после оператора if, то программа будет иметь следующий вид: if ( a>b ) if ( b < c ) t=b; else r=t; В этом случае else воспринимается как часть второго оператора if. В операторе ветвления, используемом в языке Си, для написания выражений используются следующие операции отношения: == равно != не равно > больше >= больше или равно < меньше <= меньше или равно В операциях отношения могут использоваться переменные целого, плавающего типа, а так же типа указателя, при этом в каждой операции могут участвовать переменные различных типов. Результатом операции будет 0 (ложь) или 1 (истина). Кроме арифметических операций языка С можно применять логические операции, к которым относятся: && – операция логического "И", || – операция логического "ИЛИ", ! – операция логического "НЕ". В логических операций могут использоваться переменные того же типа данных, что и в операциях отношения. Логические выражения вычисляются слева направо, при этом, если результата первого условия достаточно, чтобы определить результат всей операции, то остальные условия не вычисляются. В языке Си нет логического типа как в языке Паскаль. Вместо значений true и false в языке Си принято нулевое значение за истину, а не нулевое (чаще единица) – за ложь. Результат логических операций имеет целочисленный тип (int) и может принимать только одно из двух значений: 0 или 1. Например: 3<5 результат 1 3>5 результат 0 6!=1 || 2>5 результат 1 8>2 && 4>5 результат 0 В языке Си имеется одна тернарная операция – операция «условие» (не путать с условным оператором), которая имеет следующий формат: операнд-1 ? операнд-2 : операнд-3; Операнд-1 может быть только целого, плавающего типа или указателем. Он оценивается с точки зрения его эквивалентности 0. Если операнд-1 не равен 0 (истина), то вычисляется операнд-2 и его значение является результатом операции. Если операнд-1 равен 0 (ложь), то вычисляется операнд-3 и его значение является результатом операции. Следует отметить, что вычисляется либо операнд-2, либо операнд-3, но не оба. Тип результата зависит от типов операнда-2 и операнда-3. Пример: max = (d<=b) ? b : d; Здесь переменной max присваивается максимальное значение переменных d и b. Каждый оператор, каждое определение и каждое описание в программе на языке Си завершает точка с запятой ";". Любое допустимое выражение, за которым следует ";", воспринимается как оператор. При выполнении арифметических и логических операций следует следить за приоритетами этих операций и порядком их вычисления (таблица 2.1). Наивысшим приоритетом в языке Си является приоритет равный 1. Операции с наибольшими приоритетами вычисляются первыми. Операции одного ранга имеют одинаковый приоритет, и если их в выражении несколько, то они выполняются в соответствии с правилом ассоциативности, либо слева направо, либо справа налево. Ранг 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Табл. 2.1 Приоритеты операций Операция Ассоциативность () [] -> . справа налево ! ~ -(смена знака) ++ -- &(адрес) * (тип) sizeof слева направо */% справа налево +справа налево << >> справа налево < <= >= > справа налево == != справа налево & справа налево ^ справа налево | справа налево && справа налево || справа налево ? слева направо = *= /= %= += -= &= ^= |= <<= >>= слева направо , справа налево Использование оператора if рассмотрим на следующих примерах. Пример1: Ввести два целых числа и вывести на экран наибольшее из них. Идея решения: надо вывести на экран первое число, если оно больше второго, или второе, если оно больше первого. Составим схему алгоритма (рисунок 2.1). Окончательно программа имеет вид: #include <iostream> using namespace std; #include <conio.h> int main() { float a, b, max; cout<<"a="; cin>>a; cout<<"b="; cin>>b; if (a>b) max = a; else max = b; cout<<"max="; cout<<max; _getch(); return 0; } Рис. форма ветвления 2.1. Полная Пример2 (вложение условных операторов): Дано действительное число а. Для функции f(a), график которой представлен на рисунке 2.2, вычислить значение f(a). Рис. 2.2. График функции Этапы решения задачи: 1. Математическая модель: функция вычисляется по следующей формуле 2. Составим общую схему алгоритма (рисунок 2.3). Рис. 2.3. Алгоритм решения задачи Детализируем блок «Определяем к какому промежутку относится x» (рисунок 2.4). Рис. 2.4. Ветвление блока Добавим блоки вычисления функции на каждом из промежутков (рисунок 2.5). Рис. 2.5. Блок определения промежутка для переменной x. Окончательный алгоритм представлен на рисунке 2.6. Рис. 2.6. Общая схема вычисления функции по заданному значению x Дальнейшая детализация не требуется. Переводим блок-схему на язык С++: #include <iostream> using namespace std; #include <conio.h> int main(void) { float a, f; cout<<"a="; cin>>a; if (a<-1) f= -a-1; else if ((a>=-1) && (a<0)) f = a+1; else if ((a>=0) && (a<1)) f= -a+1; else f = a+1; cout<<"f="; cout<<f; _getch(); return 0; } Реализовав данную программу в интегрированной среде программирования, получим результирующее окно, представленное на рисунке 2.7. Рис. 2.7. Окно выполнения задачи В завершение работы хотелось бы привести перечень служебных символов (табл. 2.2), которые используются с одной стороны для организации процесса вычислений, а с другой – для передачи компилятору определенного набора инструкций. Таблица 2.2 Специальные символьные комбинации Комбинация Наименование \a Звонок \t Горизонтальная табуляция \n Переход на новую строку \v Вертикальная табуляция \r Возврат каретки \" Кавычки \' Апостроф \0 Символ с кодом ноль \\ Обратная дробная черта Примеры использования управляющего символа: cout << "Это строка один\nЭто строка два"; \\вывод двух строк cout << 1 << '\n' << 0 << '\n' << 0 << '\n' << 1 \\вывод каждого \\ из чисел 1, 0, 0 и 1, каждое на отдельной строке Задачи для индивидуального решения: 1. Написать программу вычисления площади кольца. Программа должна проверять правильность исходных данных. Ниже представлен рекомендуемый вид экрана во время работы программы (данные, введенные пользователем, выделены полужирным шрифтом): Вычисление площади кольца. Введите радиус кольца (см) —> 3.5 Радиус отверстия (см) —> 7 Ошибка! Радиус отверстия не может быть больше радиуса кольца. 2. Написать программу вычисления стоимости покупки с учетом скидки. Скидка в 10% предоставляется, если сумма покупки больше 1000 руб. Ниже представлен рекомендуемый вид экрана во время работы программы: Вычисление стоимости покупки с учетом скидки. Введите сумму покупки и нажмите <Enter> -> 1200 Вам предоставляется скидка 10% Сумма покупки с учетом скидки: 1080.00 руб. 3. Выяснить поместится ли квадрат со стороной А внутрь окружности радиусом R и если он не помещается, то выяснить поместится ли окружность внутрь квадрата. 4. Заданы вещественные числа x и y. Определить и вывести на экран монитора номер квадранта декартовой системы координат, в котором расположена точка М(x,y). 5. Проверить, можно ли из четырех отрезков, длины которых введены с клавиатуры, составить параллелограмм. Вариант 1 1. 2. Вариант 2 1. 2. Вариант 3 1. 2. Вариант 4 1. 2. Переменные X, Y, Z имеют положительные значения. Определить, можно ли построить треугольник с длинами сторон X, Y, Z. Если можно, то какой он получится: прямоугольный, остроугольный или тупоугольный. Дано целое трехзначное число. Определить, все ли цифры этого числа различны. Выяснить, принадлежит ли точка с координатами (x,y) области, ограниченной точкой начала координат и точкой с координатами x=3 и y=sqrt(x). Определить, являются ли значения целочисленных переменных N и М кратными 3. Если оба значения кратны 3, то вычислить их сумму, в противном случае - разность. Выяснить, можно ли построить треугольник из отрезков с длинами a, b, c и если треугольник существует, выяснить является ли он тупоугольным или прямоугольным. Даны целые числа X, Y. Если числа не равны, то заменить каждое из них одним и тем же числом, равным большему из исходных, а если равны, то единицей. Даны три действительных числа. Выбрать из них те, которые принадлежат интервалу (1, 3). Даны действительные числа a, b, c и x, y. Выяснить, пройдет ли кирпич с ребрами a, b, c в прямоугольное отверстие со сторонами x и y. Вариант 5 1. 2. Вариант 6 1. 2. Вариант 7 1. 2. Вариант 8 1. 2. Вариант 9 1. 2. Вариант 10 1. 2. Выяснить, поместится ли прямоугольник со сторонами А и В внутрь окружности радиусом R и если он не помещается, то выяснить поместится ли окружность внутрь квадрата. Даны значения a, b и c. Удвоить эти числа, если a>b>c, и заменить их абсолютными значениями, если это не так. Определить, есть ли среди цифр заданного четырехзначного числа одинаковые. Заданы площади круга и квадрата. Определить поместится ли квадрат внутрь круга. Два прямоугольника заданы длинами их сторон. Выяснить можно ли первый прямоугольник целиком поместить во втором. Стороны прямоугольников параллельны. Определить, какая из двух точек - M1(x1,y1) или M2(x2,y2) расположена ближе к началу координат. Вывести на экран дисплея координаты этой точки. Даны действительные числа x, y. Если x, y отрицательны, то каждое значение заменить его модулем; если отрицательное только одно из них, то оба значения увеличить на 0.5; если оба значения не отрицательны и ни одно из них не принадлежит отрезку [0.5, 2.0], то оба значения уменьшить в 10 раз; в остальных случаях x, y оставить без изменения. Выяснить, принадлежит ли точка с координатами (x,y) квадрату со стороной A и с центром в начале координат. Определить, попадает ли точка M(x,y) в круг радиусом r и центром в точке (x0,y0). Написать программу вычисления стоимости покупки с учетом скидки. Скидка в 3% предоставляется в том случае, если сумма покупки больше 500 руб., в 5% — если сумма больше 1000 руб. Рекомендуемый вид экрана во время работы программы: Вычисление стоимости покупки с учетом скидки. Введите сумму покупки и нажмите <Enter> -> 640 Вам предоставляется скидка 3% Сумма покупки с учетом скидки: 620.80 руб. Даны два целых числа X и Y. Если X четное число, а Y не четное число, то оба эти числа заменить их модулями. Если X положительное нечетное число, а Y положительное четное число, то оба эти числа увеличить на 2. Во всех остальных случаях числа оставить без изменения. Две точки заданы на плоскости своими координатами, которые могут быть как декартовыми, так и полярными. Требуется вычислить расстояние между этими двумя точками. Лабораторная работа № 3 Программирование структур ветвления с применением оператора множественной выборки Цель работы: 1) изучить правила программирования ветвящихся алгоритмов с помощью оператора множественного выбора; 2) получить практические навыки программирования задач с множественным ветвлением. Общие сведения: Кроме использования условного оператора, для осуществления выбора между двумя альтернативами в зависимости от входного значения можно использовать и оператор множественного выбора Синтаксис оператора switch: switch (выражение) { case константное выражение: оператор или группа операторов; break; case константное выражение: оператор или группа операторов; break; case константное выражение: оператор или группа операторов; break; … defaulf: оператор или группа операторов; } Результат вычисленного выражения сравнивается с каждым из константных выражений. Если находится совпадение, то управление передается оператору, связанному с данным case. Исполнение продолжается до конца тела оператора switch или пока не встретится оператор break, который передает управление из тела switch оператору, следующему за switch. Оператор или группа операторов, стоящий после ключевого слова default, выполняется, если выражение не соответствует ни одному из константных выражений в case. Константные выражения могут быть только целыми или символьными константами. Они является ключевыми для выбора из нескольких вариантов и должны быть уникальны. Каждый вариант начинается со слова case с последующим константным выражением. Помимо операторов, помеченных ключевым словом case, может быть, раздел со словом default. Схема выполнения оператора switch (отличающаяся от соответствующего оператора в языке программирования Pascal) следующая: вычисляется выражение в круглых скобках; вычисленные значения последовательно сравниваются с константными выражениями, следующими за ключевыми словами case; если одно из константных выражений совпадает со значением выражения, то управление передается на оператор, помеченный соответствующим ключевым словом case; если ни одно из константных выражений не равно выражению, то управление передается на оператор, помеченный ключевым словом default, а в случае его отсутствия управление передается на следующий после switch оператор. Ключевые слова case и default существенны только при начальной проверке, чтобы определить начальную точку выполнения тела оператора switch. Дальше выполняются все операторы от начального (определенного выражением) оператора до конца тела switch вне зависимости от ключевых слов, если только в каком-то операторе не встретится оператор break, который передаст управление из тела switch на следующий оператор за оператором switch. Пример: int i=2; switch (i) { case 1: i += 2; case 2: i *= 3; case 0: i /= 2; case 4: i -= 5; default: ; } Выполнение оператора switch начинается с оператора, находящегося после конструкции case 2. В результате вычислений переменной i присваивается значение 6, далее последовательно выполняются все операторы, стоящие ниже (строки case 0 и case 4). В процессе вычислений переменная i изменит свое значение на 3, а затем на -2. За ключевым словом default стоит пустой оператор, который не изменяет значения переменной. Другой пример: Для двух переменных x и y посчитать выражения, в зависимости от типа операции ZNAC. char ZNAC; int x,y,z; switch (ZNAC) { case '+': x = y + z; break; case '-': x = y - z; break; case '*': x = y * z; break; case '/': x = u / z; break; default : ; } Оператор break завершает выполнение оператора switch и передает управления оператору, следующему за switch. Еще один пример: switch (c) { case `A': capa++; case `a': letter++; default: total++; } при с='A' инкрементируются переменные capa, letter, total, при c='a' – letter и total, при всех остальных значениях символьных констант – только total. Пример 1. Написать программу, которая по введенному с клавиатуры номеру дня недели выводит на экран название этого дня. #include <iostream> using namespace std; #include <conio.h> int main(void) { int num; cout << "Enter number of a day of the week >"; cin >> num; // Ввод данных switch (num) // Выбор варианта { case 1: cout << "Monday" << endl; break; case 2: cout << "Tuesday" << endl; break; case 3: cout << "Wednesday" << endl; break; case 4: cout << "Thursday" << endl; break; case 5: cout << "Friday" << endl; break; case 6: cout << "Saturday" << endl; break; case 7: cout << "Sunday" << endl; break; default: cout << "Number is incorrect" << endl; } _getch(); return 0; } Реализовав данную программу в интегрированной среде программирования, получим результирующее окно, представленное на рисунке 3.1 (для номера недели 7). Рис. 3.1. Окно выполнения задачи Кроме того, в данной лабораторной работе (как преддверие к следующим работам) необходимо сказать несколько слов об объявлении переменных. Прочитайте данный раздел и используйте изложенные в нем сведения для выполнения этой и последующих работ. Объявление переменных Язык С++ требует явного объявления всех переменных используемых в программе вместе с указанием соответствующих им типов. Объявления переменной имеет следующий формат: <спецификатор типа> имя_1, имя_2, ..., имя_n; спецификатор типа – одно или несколько ключевых слов, определяющие тип объявляемой переменной. В языке С++ имеется стандартный набор типов данных, используя который можно сконструировать новые (уникальные) типы данных; имя_1, имя_2, имя_n – идентификаторы, соответствующие именам переменных. Стандартные типы данных В таблице 3.1 приведены ключевые слова, которые определяют диапазон значений и размер области памяти, выделяемой под переменные целого типа. Таблица 3.1. Целые типы данных Тип char int short long unsigned сhar unsigned int unsigned short unsigned long Размер памяти в байтах 1 2 2 4 1 2 2 4 Диапазон значений от -128 до 127 от -32768 до 32767 от -32768 до 32767 от -2 147 483 648 до 2 147 483 647 oт 0 до 255 от 0 до 65535 от 0 до 65535 от 0 до 4 294 967 295 Например: unsigned int n; int b,f2,f3; int c; long d; Отметим, что тип char используется для представления символа. Значением объекта типа char является код (размером 1 байт), соответствующий представляемому символу. Для представления символов русского алфавита, модификатор типа идентификатора данных имеет вид unsigned char, так как коды русских букв превышают величину 127. В языке С++ не определено представление в памяти и диапазон значений для идентификаторов типа int и unsigned int. Размер памяти для переменной с модификатором типа int определяется длиной машинного слова, которое имеет различный размер на разных компьютерах. Например, на 16-ти разрядных ЭВМ размер слова будет равен 2-м байтам, а на 32-х разрядных машинах - 4-м байтам, это соответствует типам short или long в зависимости от архитектуры используемой машины. Это означает, что одна и та же программа может правильно работать на одном компьютере и не работать на другом. Восьмеричные и шестнадцатеричные константы также могут иметь модификатор unsigned, для этого необходимо указать префикс u или U после константы. Константа без этого префикса считается знаковой. Например: 0xA8C (int); 01756l (long); 0xF7u (unsigned int); Данные вещественных типов В таблице 3.2 приведены типы данных, используемые для представления чисел с плавающей точкой. Тип float double long double Таблица 3.2. Вещественные типы данных Размер памяти в Диапазон значений байтах 4 3.4E-38 ... 3.4E+38 8 1.7E-308 ... 1.7E+308 10 3.4E-4932 ... 3.4E+4932 Типы double и long double кроме более широкого числового диапазона отличаются большей точностью. Примеры: float f, a, b; double x,y; Записывая арифметические выражения на языке С++, необходимо помнить и о еще одной особенности этого языка, делающей его универсальным – возможности преобразования типов. Преобразования типов Представим себе следующий оператор присваивания: int ival = 0; // обычно компилируется с предупреждением ival = 3.145 + 3; В результате переменная ival получит значение 6 (при складывании литералов разных типов – 3.145 типа double и 3 типа int). Язык C++ обычно не может сразу выполнить данную операцию, так как ему сначала необходимо привести операнды к одному типу. Для этих целей были введены правила преобразования арифметических типов, суть которых заключается в переходе от операндов меньшего типа к большему во избежание потери точности вычислений. В данном примере целое число 3 приводится к типу double, и только после этого производится сложение. Подобные преобразования осуществляются автоматически и называются неявным преобразованием типов данных. В результате сложения двух чисел уже одного типа double получится число 6.145, которое тоже будет иметь тип double. Присвоение этого числа переменной ival, которая имеет тип int, приведет к автоматическому отбрасыванию дробной части числа (а не округлением). Таким образом, 6.145 превращается в 6, и этот результат присваивается переменной ival. Такое преобразование приводит к потере точности, поэтому большинство компиляторов выдают соответствующее предупреждение. Так как компилятор не округляет числа при преобразовании double в int, при необходимости мы должны позаботиться об этом сами. Например: double dva1 = 8.6; int iva1 = 5; ival += dva1 + 0.5; // преобразование с округлением При желании мы можем произвести явное преобразование типов: // инструкция компилятору привести double к int ival = static_cast< int >( 3.145 ) + 3; В этом примере дается явное указание компилятору о приведении величины 3.145 к целому типу. Ниже представлены правила неявного и явного преобразования типов данных (как в первом и во втором примерах соответственно). Явные и неявные преобразования типов в С++. Правила неявного преобразования. Операции преобразования типа: float a=1; float b; b=a+(int)2.1; В языке С используется автоматическое приведение типа при вычислениях (при вычислениях с различными типами данных): int a=1; float b; b=a+2.1; //В результате: 3.1 Правила: 1) тип char приводится к short; 2) short – к int; 3) signed – к unsigned; 4) все целые типы преобразуются к long, а long – к unsigned long; double f; unsigned char ch; unsigned long m; int I; f*(I+ch/m) Результат операции в скобках приводится к double перед умножением. Явное приведение типа. Правила: 1) целое со знаком преобразуется к более короткому целому со знаком путем усечения старших бит: Unsigned char ch; ch=()65535 ↓ 255 Целое со знаком преобразуется к более длинному целому со знаком путем размножения знаков. 2) при преобразовании целого со знаком к целому без знака, целое число со знаком преобразуется к размеру целого без знака и результат интерпретируется как целое без знака. Unsigned char ch1; //Пример описания. В других языках такого нет. char ch2=-1; ch1=ch2 ↓ 255 3) преобразование целого со знаком к плавающему типу происходит без потери информации, за исключением случая преобразования типа long к float, тогда точность может быть частично потеряна. 4) целое без знака преобразуется к более длинному целому со знаком путем расширения нулем. 5) когда целое без знака преобразуется к целому со знаком того же размера, битовый шаблон не изменяется, однако значение, которое оно представляет, изменяется, если знаковый бит установлен. Unsigned short A1=65535; short A2=; A2=A1; A2 ↓ .1 6) величина типа float преобразуется к double без изменения значений. Величины double, преобразованные к float, представляются точно, если это возможно. 7) при преобразовании величины с плавающей точкой к целым типам они сначала преобразуются к типу long, при этом дробная часть отбрасывается, а затем величины типа long преобразуются к требуемому типу. Если значение слишком велико для long, то результат будет не определён (отбрасывается младшая часть мантиссы). Операции инкремента и декремента Операции ++ и – – это операции инкремента и декремента. Операция инкремента увеличивает значение операнда на единицу. Операция декремента уменьшает значение операнда на единицу. Например, следующий оператор: х = х + 1; с применением операции инкремента можно записать в таком виде: х++; Аналогично, оператор х = х – 1; эквивалентен оператору х– –; Эти операции отличаются тем, что они могут быть записаны как в постфиксной форме, когда символ операции следует за операндом, как в приведенных примерах, так и в префиксной форме, когда он предшествует операнду. В приведенных примерах применение любой из этих форм не имеет никакого значения. Однако, когда операции инкремента/декремента являются частью более сложного выражения, проявляется внешне незначительное, но важное различие между этими двумя формами. В префиксной форме значение операнда увеличивается или уменьшается до извлечения значения для использования в выражении. В постфиксной форме предыдущее значение извлекается для использования в выражении, и лишь после этого значение операнда изменяется. Например: х = 42; у = ++х; В этом случае значение у устанавливается равным 43, как и можно было ожидать, поскольку увеличение значения выполняется перед присваиванием значения х переменной у. Таким образом, строка у=++х эквивалентна следующим двум операторам: х = х + 1; y = х; Однако если операторы записать как х = 42; у = х++; значение переменной х извлекается до выполнения операции инкремента, и поэтому значение переменной у равно 42. Конечно, в обоих случаях значение переменной х установлено равным 43. Следовательно, строка у=х++; эквивалентна следующим двум операторам: у = х; х = х + 1; В заключении вопрос: почему язык программирования получил название С++, а не ++С? Задачи для индивидуального решения (пользуясь оператором switch): 1. По номеру y (y > 0) некоторого года определить с – номер его столетия. Учесть, что, к примеру, началом XXI столетия был 2001, а не 2000 год. 2. Даны произвольные числа a, b, c. Если нельзя построить треугольник с такими длинами сторон, то выдать соответствующее сообщение; если можно, то напечатать какой он: равносторонний, равнобедренный, разносторонний. 3. По введенному номеру месяца выдать на экран сообщение о времени года и названии введенного месяца. Например: 1 – январь, зима. 4. Даны a и b. Напечатать максимальное и минимальное значения выражений с указанием формул, по которым производились вычисления. 5. Составить программу, которая при вводе символа с клавиатуры выводит «цифра», если введена цифра; «латинская буква» при вводе латинской буквы и «не цифра и не латинская буква» во всех остальных случаях. Вариант 1 1. Вариант 2 1. Вариант 3 1. Вариант 4 1. Вариант 5 1. Вариант 6 1. Вариант 7 1. Вариант 8 1. Вариант 9 1. Вариант 10 1. По введенному времени и известному расписанию занятий вывести сообщение о том, что это: пара (с указанием ее номера) или перемена. По введенному номеру месяца вывести на экран сообщение о номере квартала. Составить программу, которая по введенному году и номеру месяца определяет число дней в этом месяце. При вводе с клавиатуры символа: + вывести сообщение «сложение»; − вывести сообщение «вычитание»; * вывести сообщение «умножение»; / вывести сообщение «деление» с указанием формулы и примера с конкретными значениями, введенными с клавиатуры. Составить программу, которая при вводе символа "{" или "}" выводит сообщение «фигурная скобка»;. при вводе "[" или "]" – «квадратная скобка»; при вводе "(" или ")" – «круглая скобка»; в остальных случаях – сообщение «не скобка». Даны произвольные числа a, b и c. Присвоить максимальное из них переменной a, минимальное - переменной с, среднее - переменной b. Составить программу, которая при вводе оценки в виде цифры выводит оценку в виде слова: 5 – отлично, 4 – хорошо, 3 – удовлетворительно, 2 – неудовлетворительно. Составить программу, которая выводит введенный возраст человека с добавлением слов «год», «года», «лет» (41 год, 3 года, 20 лет). По введенному номеру квартала вывести на экран, какие месяцы входят в этот квартал. Составить программу, которая по введенному номеру дня недели выдает его название. Например, 1 – понедельник. Лабораторная работа №4 Программирование циклических алгоритмов Цель работы: изучить циклические конструкции в языке С++, научиться составлять программы решения задач с использованием циклов. Общие сведения Алгоритм является циклическим, если он содержит многократное выполнение одних и тех же операторов при различных значениях промежуточных данных. Число повторений этих операторов может быть задано в явной (цикл с известным числом повторений) или неявной (цикл с неизвестным заранее числом повторений) форме. В ходе выполнения работы необходимо рассмотреть различные варианты организации циклов и особенности их использования. Цикл с известным заранее числом повторений (оператор for) Оператор for – является наиболее распространенным способом организации циклов и имеет следующий вид: for (выражение 1; выражение 2; выражение 3) оператор ; Выражение 1 устанавливает начальное значение переменной, управляющей циклом. Выражение 2 определяет условие, при котором тело цикла будет выполняться. Выражение 3 задает условие изменения переменной, управляющей циклом после каждого выполнения тела цикла. Схема выполнения оператора for: 1. вычисляется выражение 1. 2. вычисляется выражение 2. 3. если значения выражения 2 отлично от нуля (истина), выполняется тело цикла, вычисляется выражение 3 и осуществляется переход к пункту 2, если выражение 2 равно нулю (ложь), то управление передается на оператор, следующий за оператором for. Особенностью данного цикла является то, что проверка условия всегда выполняется в начале цикла. Это значит, что тело цикла может ни разу не выполниться, если условие выполнения сразу будет ложным. Пример: int a,b; for (a=1; a<=10; a++) b=a*a; В этом примере вычисляются квадраты чисел от 1 до 10 включительно. Возможности оператора for позволяют использовать несколько переменных для управления циклом. Пример: int t, b; char string[100], tmp; for (t=0, b=100; t < b; t++, b--) { tmp=string[t]; string[b]=tmp;} В данном примере показана запись строки символов в обратном порядке. Для управления циклом здесь используются две переменные t и b записанные через запятую и выполняемые последовательно. Еще одним вариантом использования оператора for является бесконечный цикл. Для организации такого цикла используется пустое условное выражение, а для выхода из цикла применяется дополнительное условие и оператор break. Пример: for (;;) { ... ... ... break; } Так как в языке Си оператор может быть пустым, значит и тело оператора for также может быть пустым. Такая форма оператора может быть использована для организации поиска. Пример: for (i=0; t[i]<10 ; i++); В данном примере переменная цикла i принимает значение номера первого элемента массива t, значение которого больше 10. Цикл с предусловием (оператор while) Оператор while называется циклом с предусловием и имеет следующий вид: while (выражение) оператор; В качестве выражения можно использовать любое выражение языка Си, а в качестве тела любой оператор, в том числе пустой или составной. Схема выполнения оператора while следующая: 1. вычисляется выражение. 2. если выражение истинно, то выполняется тело оператора while, если ложно, то выполнение цикла заканчивается. 3. процесс повторяется с пункта 1. Так же как и в цикле со счетчиком for, в операторе while вначале происходит проверка условия. Поэтому оператор while удобно использовать в ситуациях, когда тело оператора не всегда нужно выполнять. Внутри операторов for и while допускается использовать локальные переменные, которые должны быть объявлены с определением соответствующих типов. Цикл с постусловием (оператор do while) Оператор цикла do while называется оператором цикла с постусловием и используется в тех случаях, когда тело цикла необходимо выполнить хотя бы один раз. Формат оператора имеет следующий вид: do тело while (выражение); Схема выполнения оператора do while: 1. выполняется тело цикла. 2. вычисляется выражение. 3. если выражение ложно, то выполнение оператора do while заканчивается и выполняется следующий по порядку оператор. Если выражение истинно, то выполнение оператора продолжается с пункта 1. Чтобы прервать выполнение цикла до того, как условие станет ложным, можно использовать оператор break. Операторы while и do while могут быть вложенными. Пример: int i,j,k; ... i=0; j=0; k=0; do {i++; j--; while (k < i) k++; } while (i<30 && j<-30); Использование операторов цикла рассмотрим на следующем примере. Пример 1: На промежутке от 1 до M найти все числа Армстронга. Натуральное число из n цифр называется числом Армстронга, если сумма его цифр, возведенных в n-ю степень, равна самому числу. Например, десятичное число 153 – число Армстронга, потому что: 1³ + 5³ + 3³ = 153. Другие примеры начальных чисел Армстронга в десятичной системе счисления: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 153, 370, 371, …. Числа 153, 370, 371 и 407 имеют специальное название – числа Армстронга (в честь математика, который их впервые исследовал). Строгое математическое определение таково: n-значное число называется числом Армстронга, если оно равно сумме n-ых степеней своих цифр. Числа Армстронга n Числа Армстронга n 3 153; 370; 371; 407 8 24678050; 24678051; 88593477 4 1634; 8208; 9474 9 146511208; 472335975; 534494836; 912985153 5 54748; 92727; 93084 10 4679307774 6 548834 11 32164049650; 32164049651; 40028394225; 42678290603; 44708635679; 49388550606; 82693916578; 94204591914 7 1741725; 4210818; 9800817; 9926315 14 28116440335967 Этапы решения задачи: 1. Математическая модель: x [1;M], x= 2. Составим блок схему программы (рисунок 4.1). = Рис. 4.1. Алгоритм решения задачи 3. Распишем составные части блока «Находим все числа Армстронга на заданном промежутке и печатаем их» (рисунок 4.2). Рис. 4.2. Алгоритм решения основного блока задачи 4. Опишем блок «Подсчитываем сколько цифр в числе i» (рисунок 4.3) Рис. 4.3. Алгоритм подсчета количества цифр в числе i 5. Опишем блок «Проверяем, является ли i числом Армстронга» (рисунок 4.4) Рис. 4.4. Алгоритм проверки числа Армстронга Дальнейшая детализация не требуется, запишем блок-схему целиком (рисунок 4.5). Рис. 4.5. Общая схема вычисления числа Армстронга Дальнейшей детализации не требуется, переведем программу на язык С++. #include <iostream> using namespace std; #include <math.h> int main() { int i,k,s,p,n, M; cout<<"Vvedite M:"; cin>>M; for (i=1; i<=M; i++) { s=0; k=i; n=0; while (k!=0) { k=k/10; n=n+1; } k=i; while (k!=0) { p=k%10; k=k/10; if (p!=0) s=int(s+exp(n*log(float (p)))); } if (s==i) cout<<i<<"\n"; } return 0; } Реализовав данную программу в интегрированной среде программирования, получим результирующее окно, представленное на рисунке 4.6. Рис. 4.6. Окно выполнения задачи Задачи для индивидуального решения: 1. Написать программу, которая выводит таблицу квадратов первых десяти целых положительных чисел. 2. Вычислить S=1+1/2+1/3+1/4+....+1/10. 3. В промежутке 20…32 найти все числа кратные числу S, введенному с клавиатуры. 4. Среди введенных с клавиатуры 6 чисел найти максимальное и минимальное из введенных чисел. 5. Дана последовательность 8 чисел. Определить сколько раз в этой последовательности изменяется знак числа. Вариант 1 2. 3. Вариант 2 1. 2. Вариант 3 1. 2. Вариант 4 1. 2. Вариант 5 1. 2. Вариант 6 1. 2. Вариант 7 1. 2. Вариант 8 1. 2. Вариант 9 1. 2. Вариант 10 1. 2. Среди введенных с клавиатуры 6 чисел подсчитать количество положительных и количество отрицательных чисел. Дано число А. Написать программу получения в порядке убывания всех делителей данного числа. Вычислить S=1+(1*2)+ (2*3)+ (3*4)+....+ (9*10). Дана последовательность чисел, ввод которой заканчивается вводом нуля. Определить сколько раз в этой последовательности изменяется знак числа. Среди введенных с клавиатуры 10 чисел найти количество четных чисел и их среднее арифметическое. Дано целое четырехзначное число n. Найти сумму цифр числа n. Вычислить S=1+1/3+ 2/5+ 3/7+....+ 6/13. Дана последовательность чисел. Определить, со скольких отрицательных подряд идущих чисел она начинается. Среди введенных с клавиатуры 8 чисел подсчитать количество положительных и количество отрицательных чисел. Используя алгоритм Евклида, найти наименьшее общее кратное m и n. Вычислить S=1+1/(1*2)+ 2/(1*2*3)+ 3/4!+....+ 5/6!. Составить программу, которая распечатывает на экране таблицу умножения. Дано целое натуральное n. Определить, сколько цифр в числе n? Среди введенных с клавиатуры чисел найти количество четных чисел и их среднее арифметическое. Ввод чисел заканчивается вводом нуля. Дано натуральное n. Написать программу вычисления значений S=1+1/(1*2)+1/(1*2*3)+....+1/(n!) Вывести на экран числа, кратные К из промежутка [А,В]. Числа А, В, К задает пользователь. 3 Найти наибольшее и наименьшее значение функции у=x на интервале x1 до x2, перебирая значения функции с шагом H=0.01. Дано целое число натуральное n. Найти сумму цифр числа n. Составить программу, проверяющую, является ли последовательность из 10 целых чисел, вводимых с клавиатуры, монотонно возрастающей. Напечатать все двузначные числа, в которых нет одинаковых цифр. Лабораторная работа №5 Структурированный тип данных - массив Цель работы: получить представление о структурированном типе данных "массив", научиться инициализировать массивы, распечатывать содержимое массива и решать задачи с применением массивов. Общие сведения Язык Си имеет базовые или встроенные типы данных, которые позволяют строить другие типы и структуры данных: char (символьные), int (целые), float (с плавающей точкой), double (с плавающей точкой двойной длины), void (пустой, не имеющий значения). На основе этих пяти типов строятся дальнейшие типы данных, олин из которых – массив. Массив – это структурированный тип данных, который используется для описания упорядоченной совокупности фиксированного числа элементов одного типа, имеющих общее имя. Для обозначения элементов массива используются имя переменной-массива и индекс. Массив – это одна из известных и наиболее простых структур данных. Массив определяется именем массива и порядковым номером каждого своего элемента. Обычно порядковый номер элемента называют индексом. Индекс (т.е. порядковый номер элемента) в языке Си всегда целое число. Перед использованием массива в использующей его программе он (массив) должен быть обязательно объявлен. При этом указывается имя массива и его размерность, как максимальное количество элементов в массиве. Основная форма объявления массива следующая: тип <имя массива> [размер1][размер2]...[размер N]; Чаще всего используются одномерные массивы. Их форма описания такова: тип <имя массива> [размер1]; Слово «тип» в описании – это один из базовых (основных) типов элементов массива. Размер – это, как выше было сказано, количество элементов одномерного массива. Все дело в том, что в двухмерном массиве размер определяется с помощью умножения. При описании двумерного массива его объявление будет таково: тип <имя массива> [размер1] [размер2]; Это будет массив массива, т.е. массив размера [размер2], элементами которого являются одномерные массивы: <имя массива> [размер1]. Размер массива в языке Си задается константой или константным выражением. Нельзя задавать массив переменного размера. Для этого существует отдельный механизм, называемый динамическим выделением памяти (данный механизм будет изучаться позже). В языке Си нумерация элементов начинается с нуля. Т.е. минимальный неотрицательный индекс элемента есть число – ноль. Таким образом, всегда первый элемент массива – это элемент с нулевым номером. Предположим, что объявлен массив int a[100]; Это означает, что массив содержит следующие элементы: a[0], a[1], a[2],..., и так далее, a[99]. Легко подсчитать, сколько байт памяти потребуется под одномерный массив: Количество байт = <размер базового типа> * <количество элементов в массиве> Следует знать, что в языке Си под массив всегда выделяется непрерывное место в оперативной памяти. Выход массива за свои определенные командой пределы в Си не проверяется. Это следует помнить. То есть, например, если массив имеет 100 элементов и описан как a[100], то при обращении к элементу a[200] язык Си не дает программе средств для контроля того факта, что имеется выхода за пределы памяти, отведенной под массив. Программа на языке Си не выдаст сообщение об ошибке. Такие возможности разработчиками не предусмотрены. Возможно потому, что в те времена особенно дефицитным ресурсом была память и ее экономили на сам транслятор и потому не уделяли такого внимания анализу ошибок программиста. Отметим, что можно определять массивы любого ранее рассмотренного типа: unsighed arr[40], long double al[1000], char ch[80]. Пример 1: Вычисление суммы квадратов элементов массива. Этапы решения задачи: 1. Алгоритм решения данной задачи заключается в том, чтобы вначале ввести содержимое массива с клавиатуры, а затем, используя цикл, осуществить расчет суммы элементов массива. 2. На рисунке 5.1 представлена схема алгоритма. Рис. 5.1. Блок-схема алгоритма решения задачи Реализация блок-схемы на языке С++: #include <iostream> using namespace std; #include <conio.h> int main() { const int N = 10; int i; double V[N], Sum = 0.0; //ввод массива cout << "Vvedite elementy massiva:\n"; for (i = 0; i < N; i++) { cout << "V[" << i << "] -> "; cin >> V[i]; } //подсчет суммы квадратов элементов массива for (i = 0; i < N; i++) Sum = Sum + V[i]*V[i]; cout << "Summa kvadratov elementov rjada ravna " << Sum << "\n"; _getch(); return 0; } Реализовав данную программу в интегрированной среде программирования, получим результирующее окно, представленное на рисунке 5.2. Рис. 5.2. Окно выполнения задачи Пример 2: Дан двумерный массив. В каждой строке все его элементы, не равные нулю, переписать (сохраняя порядок) в начало строки, а нулевые элементы – в конец массива (при этом новый массив использовать запрещается). Этапы решения задачи: 1. Суть одного из алгоритмов решения данной задачи состоит в том чтобы «просматривать» массив построчно и находить в каждой строке пару (0 – число), а затем менять их местами между собой и так до тех пор пока в строке таких пар не окажется. 2. Напишем программу на псевдо-паскале: program example1; var V:array[1..100,1..100] of integer; m,n, i,j, c: integer; flag: boolean; begin <ввод размерности массива m*n> <заполнение ячеек массива> for i:=1 to m do repeat flag:= true; for j:=1 to n-1 do if (v[i,j]=0) and (v[i,j+1]<>0) then begin <поменять их местами> flag:= false; end; until flag; <Печать массива> readln; end. 3. Составим схему алгоритма (рисунок 5.3). 4. Детализируем блок «Упорядочиваем 1-ю строку» (рисунок 5.4). Рис. 5.3. Блок-схема алгоритма решения задачи Окончательный алгоритм представлен на рисунке 5.5. Рис. 5.4. Детализация блока «Упорядочиваем 1-ю строку» Рис. 5.5. Общая схема вычисления задачи Дальнейшая детализация не требуется. Переводим блок-схему на язык С++: #include <iostream> using namespace std; #include <conio.h> int main() { int V[100][100]; int m,n,i,j,tmp; bool flag; cout<<"Vvedite koli4estvo strok:"; cin>>m; cout<<"Vvedite koli4estvo stolbcov:"; cin>>n; cout<<"\nIshodnyj massiv:\n"; for (i=0; i<=m-1; i++) for (j=0; j<=n-1; j++) { cout<<"V["<<i+1<<","<<j+1<<"]= ";cin>>V[i][j]; } for (i=0; i<=m-1; i++) { tmp=0; do {flag=true; for (j=0;j<n-1; j++) if ((V[i][j]==0) && (V[i][j+1]!=0)) {tmp=V[i][j]; V[i][j]=V[i][j+1]; V[i][j+1]=tmp; flag=false;} } while (flag); } cout<<"Otsort massiv:\n"; for (i=0; i<=m-1; i++) { for (j=0; j<=n-1; j++) cout<<"["<<i+1<<","<<j+1<<"]= "<<V[i][j]<<" cout<<"\n";}; _getch(); return 0; } "; Реализовав данную программу в интегрированной среде программирования, получим результирующее окно, представленное на рисунке 5.6. Рис. 5.6. Окно выполнения задачи Контрольные вопросы Каким образом задаются переменные типа одномерный и двумерный массив? Как модно выполнить доступ к отдельным элементам одномерного и двумерного массива? Каким образом выводятся элементы массива на экран? Как вывести на экран двумерный массив в виде матрицы. Сколько чисел можно записать в шестимерный массив: int X[1][1][1][1][1][1] Задачи для индивидуального решения (часть 1): 1. Подсчитать число и сумму положительных и число и произведение отрицательных элементов массива. 2. Дан одномерный массив, содержащий информацию о росте учеников класса. Написать программу, которая определяет количество учеников в классе, чей рост превышает средний. 3. В заданном массиве определить число соседств двух чисел одного знака, причем абсолютная величина первого из них должна быть больше второго. 4. Написать программу, которая проверяет, есть ли во введенном с клавиатуры одномерном массиве элементы с одинаковым значением и вывести их на экран. 5. Задать в массив значения функции f(x) = kx + b, при x= 1,2, …100 и вывести его на экран. Вариант 1 1. 2. Вариант 2 1. 2. Вариант 3 1. 2. Вариант 4 1. 2. Вариант 5 1. 2. Вариант 6 1. 2. Вариант 7 1. 2. Вариант 8 1. Задать в массив значения функции f(x) = 1/x + b, при x= 1,2, …50 и вывести его на экран. В массиве подсчитать количество отрицательных элементов, предшествующих максимальному элементу массива и заменить нулями все отрицательные элементы массива. Дан массив А[1..n] из целых чисел. Получить элементы, которые находятся между min и max. Написать программу, которая вычисляет среднее арифметическое ненулевых элементов введенного с клавиатуры одномерного массива целых чисел. Определить сумму элементов одномерного массива. Элементы массива X(n) переписать в массив Y(n) в обратном порядке. Задать в массив значения функции f(x) = x2 + b, при x= 1,2, …10 и вывести его на экран. В заданном массиве определить число соседств двух положительных чисел и двух чисел разного знака. Определить количество положительных чисел в массиве. Написать программу, которая выводит минимальный элемент введенного с клавиатуры массива целых чисел. В массиве А(10) найти наибольший среди отрицательных элементов. Осуществить циклический сдвиг компонентов массива на одну позицию влево. В одномерном массиве найти максимальный элемент и его индекс. Написать программу, которая вычисляет, сколько раз введенное с клавиатуры число, встречается в одномерном массиве. Сформировать массив по правилу: A[i]=A[1]+A[2]+...+A[i-1], первый элемент вводится с клавиатуры. 2. Вариант 9 1. 2. Вариант 10 1. 2. Найти самый часто встречающийся элемент из массива Проверить соблюдается ли для заданного массива правило: A[i]=A[i1]+A[i-2]] где i=2,3,..n. Дан массив X(N). Получить новый массив Y(N) такой, что в нем сначала идут положительные числа, затем нулевые, и затем отрицательные из X. Подсчитать количество элементов массива после последнего положительного элемента. Найти номер первого четного элемента одномерного массива из целых чисел. Задачи для индивидуального решения (часть 2): 1. Вычислить суммы элементов столбцов заданной матрицы A(n,m). 2. Подсчитать сколько раз встречается в заданной матрице максимальное по величине число. 3. Умножить столбец с минимальным элементом на число Z. 4. Занести в массив значения функции f(x, y) = x + y, 0<= x<=20, 0<= y <=10 и вывести его на экран. 5. Написать программу ввода с клавиатуры массива размером 6х3 и поиска в нем максимального элемента. Вариант 1 1. 2. Вариант 2 1. 2. Вариант 3 1. 2. Вариант 4 1. 2. Вариант 5 1. 2. Вариант 6 1. 2. Вариант 7 1. Написать программу ввода с клавиатуры массива размером 3х3 и вычисления произведения введенных элементов. В заданной матрице найти минимальный элемент в диагоналях. Занести в массив значения функции f(x, y) = 1/(x + y), 0<= x<=10, 0 <= y <=20 и вывести его на экран. Найти максимальную из столбцевых сумм. В каждой строке матрицы определить является ли отрицательных элементов четным или нечетным числом. В матрице поменять местами строку и столбец с номером N. сумма ее Занести в массив значения функции f(x, y) = (x + y)2, 0<= x<=5, 0<= y <=3 и вывести его на экран. В заданном массиве определить число соседств двух положительных чисел и двух чисел разного знака Найти наибольший элемент матрицы и номер строки и столбца на пересечении которых он находится. Сдвинуть циклически элементы в столбцах матрицы на одну позицию вверх. В заданной матрице поменять местами строки с номерами A и Q. Найти количество элементов матрицы, больших среднего арифметического всех ее элементов. Занести в массив значения функции f(x, y) = x - y, 0<= x<=20, 0 <= y <=10 и вывести его на экран. 2. Вариант 8 1. 2. Вариант 9 1. 2. Вариант 10 1. 2. Найти минимальную из строковых сумм. В матрице вычислить суммы элементов, стоящих над главной диагональю и под ней. Вычислить матрицу С[i,j], являющуюся суммой матриц А[i,j] и В[i,j]. Разделить все элементы столбца, в котором находится минимальный элемент матрицы на максимальный элемент матрицы. Сдвинуть циклически элементы в строках матрицы на одну позицию вправо. Написать программу ввода с клавиатуры массива размером 2х5 и вычисления суммы введенных элементов. По трем заданным матрицам A[n,m] , B[n,m] , C[n,m] построить матрицу X того же размера, каждый элемент которой вычисляется по формуле x[i,j]=max(a[i,j],b[i,j],c[i,j]. Лабораторная работа №6 Методы сортировки массива Цель работы: познакомиться с общими идеями сортировки массивов, научиться создавать алгоритмы сортировки массивов, переводить их на язык С++, отлаживать реализованные программы с использованием системы Microsoft Visual Studio. Общие сведения: Сортировка – это размещение данных в порядке возрастания или убывания. Сортировка массива осуществляется по значению его элементов. Существует множество способов сортировки. Рассмотрим три простых метода на примере сортировки целочисленных массивов данных по возрастанию. Сортировка методом выбора Алгоритм состоит в следующем. Среди элементов массива выбирается наименьший и меняется местами с первым. Далее рассматриваются элементы, начиная со второго, и наименьший из них меняется местами со вторым элементом. Так продолжается N-1 раз. При последнем проходе цикла при необходимости меняются местами предпоследний и последний элементы массива. Словесное описание приведенного алгоритма переводим на язык С++: #include <iostream> using namespace std; #include <conio.h> int main () { const int N = 9; int mas[N] = {420, 79, 429, 53, 908, 140, 897, 594, 682}; int i, j, indMin, temp; for (i = 0; i < N-1; i++) { //принимаем за наименьший первый из рассматриваемых элементов indMin = i; //поиск номера минимального элемента из неупорядоченных for (j = i + 1; j < N; j++) if (mas[j] < mas[indMin]) indMin = j; //обмен элементов с номерами i и indMin temp = mas[i]; mas[i] = mas[indMin]; mas[indMin] = temp; } //выводим упорядоченный массив на экран cout<<"Otsortirov. massiv"<<endl; for (i = 0; i < N-1; i++) cout<<mas[i]<<endl; _getch(); return 0; } На рис. 6.1 продемонстрирован процесс выполнения алгоритма сортировки методом выбора. Минимальные во время поиска элементы выделены полужирным шрифтом. Как видно, массив из 9 элементов сортируется за 8 проходов внешнего цикла for. Исходный массив 1-й 2-й 3-й 4-й 5-й 6-й 7-й 8-й проход проход проход проход проход проход проход проход цикла цикла цикла цикла цикла цикла цикла цикла 420 53 53 53 53 53 53 53 53 79 79 79 79 79 79 79 79 79 429 429 429 140 140 140 140 140 140 53 420 420 420 420 420 420 420 420 908 908 908 908 908 429 429 429 429 140 140 140 429 429 908 594 594 594 897 897 897 897 897 897 897 682 682 594 594 594 594 594 594 908 908 897 682 682 682 682 682 682 682 897 908 indMin 3 1 5 3 5 7 8 8 Рис. 6.1. Пример сортировки методом выбора Реализовав вышеприведенную программу в интегрированной среде программирования, получим результирующее окно, представленное на рисунке 6.2. Рис. 6.2. Окно выполнения задачи Сортировка методом «пузырька» Метод «пузырька» (или метод простого обмена) заключается в сравнении пары соседних элементов и замене их местами, если первый оказался больше второго. После этого сравнивается следующая пара и т.д. При выполнении этой последовательности действий элементы с большими значениями будут продвигаться (“всплывать” как пузырьки) в конец массива. Тот же массив этим методом сортируется следующей программой на языке С++: #include <iostream> using namespace std; #include <conio.h> int main () { const int N = 9; int mas[N] = {420, 79, 429, 53, 908, 140, 897, 594, 682}; int bound, t, j, temp; bound = N-1; do { t = 0; for(j = 0; j <= bound-1; j++) if (mas[j] > mas[j + 1]) { temp = mas[j]; mas[j] = mas[j + 1]; mas[j + 1] = temp; t = j; } bound = t; } while (t); //выводим упорядоченный массив на экран cout<<"Otsortirov. massiv"<<endl; for (j = 0; j < N-1; j++) cout<<mas[j]<<endl; _getch(); return 0; } В начале сортировки ничего не известно о порядке размещения элементов. В переменной bound хранится индекс самого правого элемента массива, о котором не известно, занял ли он свою окончательную позицию или нет. В переменной t хранится индекс самого последнего элемента массива, который участвовал в обмене. Если после просмотра массива переменная t равна 0, то все элементы массива упорядочены и сортировка завершена. В противном случае, продолжаем просмотр массива, исключая элементы с индексом от t до N-1, которые уже заняли свои окончательные позиции. Пример выполнения сортировки методом пузырька для массива из 9 элементов {420, 79, 429, 53, 908, 140, 897, 594, 682} приведен на рис. 6.3. Рис. 6.3. Пример сортировка методом «пузырька» Как видно, после каждого прохода массива все элементы, расположенные правее самого последнего, который участвовал в обмене, и сам этот элемент занимают свои окончательные позиции (на рис. 6.3 эта часть массива отделена вертикальной чертой). При следующих просмотрах их проверять уже не нужно. Обратите внимание на то, что после третьего прохода еще четыре правых элемента {420, 429, 594, 682} сразу заняли свои позиции, а при последнем проходе перемещений элементов вообще не было. Реализуем описанный алгоритм на языке С++. В результате будет получен следующий результат (рисунок 6.4.) Рис. 6.4. Окно выполнения задачи Сортировка методом простых вставок Пусть существующие m из N элементов массива уже упорядочены, т.е. mas[0] ≤ mas[1] ≤ … ≤ mas[m-1], а элементы mas[m], mas[m+1], …, mas[N-1] не известны. Метод сортировки вставкой применяется в тех случаях, когда массив надо заполнить так, чтобы после вставки каждого нового элемента сохранилась его упорядоченность. Для этого осуществляется поиск подходящего для вставки места в уже заполненной части массива. Место для нового элемента освобождается путем сдвига больших элементов к концу массива. На языке С++ программа выглядит следующим образом: #include <iostream> using namespace std; #include <conio.h> int main () { const int N = 9; int mas[N] = {79, 420, 429}; int i, j, m, el; m = 3; //заполнение пустой части массива for (i = m; i < N; i++) { //ввод нового элемента cout<<"Vvedite novyj element:"; cin >> el; //поиск и высвобождение места под новый элемент j = i - 1; while (j >= 0 && el < mas[j]) { //перемещение элемента mas[j] в позицию mas[j+1] mas[j+1] = mas[j]; j--; } //вставка нового элемента в массив mas[j+1] = el; } //выводим упорядоченный массив на экран cout<<"Otsortirov. massiv"<<endl; for (j = 0; j < N; j++) cout<<mas[j]<<endl; _getch(); return 0; } Поиск ведется с конца заполненной части к началу массива следующим образом. Новый элемент el сравнивается по очереди с элементами mas[m-1], mas[m-2], mas[m-3], … До тех пор, пока el меньше текущего элемента и не достигнуто начало массива, происходит высвобождение под него места путем перемещения большего элемента mas[j] на одну позицию к концу массива. Новый элемент помещается в освободившуюся позицию. Пример заполнения массива с помощью алгоритма сортировки вставкой приведен на рис. 6.3. Здесь к уже существующим элементам {79, 420, 429} (m=3) добавляются новые: 53, 908, 140, 897, 594, 682. ^ 79 420 429 : 53 79 420 429 53 79 420 429 140 420 53 53 53 53 79 79 79 79 ^ 140 140 140 53 420 420 420 :908 ^ 908 :140 429 429 429 429 ^ ^ 908 :897 897 908 :594 897 908 :682 682 897 908 594 594 ^ Рис. 6.5. Пример сортировки методом простых вставок Выполнив данную программу с помощью среды Microsoft Visual Studio 2010, получим окно, представленное на рисунке 6.6. Рис. 6.6. Окно выполнения задачи Для заполнения пустого массива нужно прежде ввести первый элемент (m=1), а после выполнить действия алгоритма сортировки вставкой. Видоизмененная программа имеет вид: const int N = 9; int mas[N]; int i, j, el; //заполнение пустой части массива cout<<"Vvedite pervyj element:"; cin >> mas[0]; for (i = 1; i < N; i++) { cout<<"Vvedite sleduwij element:"; cin >> el; j = i - 1; while (j >= 0 && el < mas[j]) { mas[j+1] = mas[j]; j--; } mas[j+1] = el; } Результирующее окно при выполнении этой программы представлено на рисунке 6.7. Рис. 6.7. Окно выполнения задачи Задачи для индивидуального решения: 1. Написать программу для заполнения данными одномерного массива в соответствии с номером своего варианта. 2. Отсортировать полученный массив по возрастанию методами выбора, «пузырька» и простых вставок. 3. Сделать выводы о полученных результатах работы программ. Варианты заданий Одномерный массив Вариант 1. Записать в массив значения функции f (x) = kx + b, при x = 1,2,...,100. 2. Записать в массив значения функции f (x) = asin(x /100) , при x = 1,2,...,100. 3. 4. 5. 6. 7. 8. Написать программу ввода в массив 20 чисел. Записать в массив значения функции f (x) = a cos(x / 50) , при x = 1,2,...,100. Написать программу ввода в массив 10 чисел. Записать в массив значения функции f (x) = x2 + b , при x = 1,2,...,10. Написать программу ввода в массив 15 чисел. Записать в массив значения функции f (x) = x3 + 5/b , при x = 1,2,...,10. 9. Записать в массив значения функции f (x) = 1/ x + b , при x = 1,2,...,50. 10. Записать в массив значения функции f (x) = k/x + b, при x = 1,2,...,100. Лабораторная работа № 7 Обработка символьной информации, работа со строками Цель работы: познакомить с понятием «строка» и получить навыки работы с символьной информацией в языке программирования С++, научиться использовать строки символов и множества при решении задач. Общие сведения Символьная константа является символом, заключенным в апострофы. Управляющая последовательность рассматривается как одиночный символ и ее допустимо использовать в символьных константах. Значением символьной константы является числовой код символа. Например: ' ' – пробел , 'Q' – буква Q , '\n' – символ новой строки, '\\' – обратная дробная черта, '\0' – символ с нулевым кодом В языке C++ для хранения однобайтового символа используется тип данных char. Переменную типа char можно рассматривать двояко: как целое число, занимающее 1 байт и способное принимать значения от -128 до 127 (тип signedchar, есть также беззнаковая модификация unsignedchar, принимающая значения от 0 до 255) и как один символ текста. Само по себе определение char может оказаться как знаковым, так и беззнаковым, в зависимости от операционной системы и компилятора. Поэтому использовать тип char не рекомендуется, лучше явно указывать будет ли он знаковым (signed) или беззнаковым (unsigned). Как и целые числа, данные типа char можно складывать, вычитать, умножать и даже делить. Но если операции умножения и деления, как правило, бессмысленны, то сложение и вычитание вполне осмысленно. Например, если к символу 'A' прибавить 1, то получится символ 'B', а если вычесть 1, то получится символ '@'. То есть в следующем фрагменте кода на экран будет выведена буква B. char c = 'A'; c = c + 1; cout<<c<<endl; В этом примере видно, что переменным типа char можно присваивать значения, равные ASCII кодам символов, если эти символы заключать в кавычки. То есть запись 'A' будет соответствовать символу A, или ASCII коду 65. Кроме того, этот пример показывает, что при выводе на экран переменной типа char мы увидим изображение этого символа. Значение ASCII-кода символа не нужно узнавать, сам символ – это и есть ASCII-код. Для того.чтобы вывести его на экран необходимо преобразовать значение величины типа char к значению типа int. Например: cout<< (int) c<<endl; Имя типа, записанное в скобочках перед значением, это и есть оператор преобразования значения к указанному типу. Аналогично, при считывании переменной типа char через поток cout, из потока ввода считывается один символ, переменная получает значение, равное его ASCII-коду. Например, если написать программу, содержащую строку: char c; cin>>c; затем запустить ее, ввести символ A (без всяких кавычек!), то в переменную c будет записано значение 65 – ASCII-код символа A. Переменным типа char можно и явно присваивать числовые значения. Например: #include <iostream> using namespace std; int main() { unsigned char c = 'A'; cout<< c << " " << (int) c <<endl; c = 126; // char можно присвоить и числовое значение cout<< c << " " << (int) c <<endl; return 0; } Эта программа выведет две строки: “A 65” и “~ 126”, то есть символы с ASCIIкодами 65 (A) и 126 (~) и сами ASCII-коды. Организовать последовательное посимвольное считывание всего входного потока можно при помощи цикла while: #include <iostream> using namespace std; int main() { char c; while (cin>>c) // Цикл пока считывание успешно { // Делаем необходимые действия, // обрабатывая символ c } return 0; } В этом примере программа будет посимвольно считывать входной поток (по умолчанию – ввод с клавиатуры), пока не встретит признак конца файла. Для того, чтобы сообщить программе о завершении входного потока при вводе с клавиатуры необходимо нажать клавиши Ctrl-d в системе Linux и Ctrl-z в системе Windows. Эта программа при считывании данных будет игнорировать символы–разделители: пробелы, символы новой строки и табуляции. Если нужно, чтобы в переменную c считывались все символы, в том числе и разделители, то необходимо для потока ввода cin установить манипулятор noskipws при помощи инструкции: cin>>noskipws; Строковой константой называется последовательность любых символов заключенных в кавычки (") . Например: "Адыгейский государственный университет", "город Майкоп", "YZPT КОД". Все управляющие символы, кавычка ("), обратная дробная черта (\) и символ новой строки в строковой и символьной константах представляются соответствующими управляющими последовательностями. Каждая управляющая последовательность представляется как один символ. Например, при выводе на экран строки "Адыгейский \n государственный университет" его часть "Адыгейский" будет напечатана на одной строке, а вторая часть "государственный университет" на следующей строке. В конец каждой строковой константы компилятором автоматически добавляется нулевой символ (признак конца строки), представляемый управляющей последовательностью \0. Строки имеют тип char[] - это означает, что строка представляется как массив символов. Отметим, что тип char используется для представления символа. Строки в языке C++ Текстовая строка – это последовательность символов. Поскольку символы в строке пронумерованы, то естественным представлением для строки был бы массив символов. Так строки и представлялись в языке Cи – строкой считался массив символов, а для обозначения конца строки использовался символ с ASCII-кодом 0, что позволяло хранить строки переменной длины (то есть в массиве char[n] можно было хранить строки любой длины, не превосходящей n-1. Такой способ хранения строк порождал ряд неудобств: любая строка была ограничена по длине размером массива, а чтобы вычислить длину строки необходимо было пройти по всей строке до появления нулевого символа, то есть определение длины строки требует количество операций, пропорциональное этой длине. В языке C++ для представления строк существует более совершенный тип данных string, в основе которого лежит такой же массив символов, завершающийся нулевым символом, но содержащий еще ряд дополнительных возможностей. Для работы со строками языка C++ необходимо в начале программы подключить описание типа string, которое находится в одноименном файле: #include <string> Переменная для хранения строковых данных объявляется так: string S; Присвоить строковой переменной некоторое константное значение можно так: S = "Hello, world!"; В рассмотренных ранее примерах мы уже встречались записью строк в тексте программы в кавычках – когда выводили текст в поток cout. Обратите внимание – константы типа char записываются в одинарных кавычках, а строки – в двойных кавычках. В частности, 'A' – это символ, а "A" – это строка, состоящая из одного символа. Поэтому переменной типа char нельзя присвоить значение "A", поскольку они имеют несовместимые типы данных. По сути, переменная типа string является массивом символов и с каждым символом этой строки можно работать по отдельности, обращаясь к ним по индексу, как к элементам массива. Например: cout<<S[0]; // Будет выведен символ H S[0] = 'h'; // Изменили первый символ в строке cout<< S; // Будет выведено hello, world! Для определения длины строки есть метод size(), применяемый к строке. Он возвращает целое число – количество символов в строке. Его можно использовать так: string S; cin>>S; cout<< "Вы ввели слово " <<S<< " в котором " <<S.size() << " символов" <<endl; Для начала нам понадобится две операции над строками: сложение двух строк и изменение размера строки. Основная операция над строками – сложение: например, при сложении строк "Hello, " и "world!" получится строка "Hello, world!". Такая операция над строками называется конкатенацией. Пример использования конкатенации строк: string S, S1, S2; // Объявление трех строк cout<< "Who are you? "; cin>>S1; // Считали строкуS1 S2 = "Hello, " // Присвоили строке значение S = S2 + S1; // Использование конкатенации cout<<S<<endl; // Вывод строки на экран cout<<S.size(); // Длина строки S Другая операция – изменение размера строки. Для этого существует метод resize, который применяется к строке. У метода resize есть две формы записи: с одним и с двумя параметрами. Если он вызывается с одним параметром, то этот параметр задает новую длину строки. Например, так: string S = "abcdefg" S.resize(3); cout<<S<<endl; // Будет выведено abc Второй параметр метода resize задает символ, которым будут заполнены символы в строке, если размер строки увеличивается в результате изменения размера. Например: string S = "abc" S.resize(6, 'd'); cout<<S<<endl; // Будет выведено abcddd При считывании строк из входного потока считываются все символы, кроме символов–разделителей (пробелов, табуляций и новых строк), которые являются границами между строками. Например, если при выполнении следующей программы String S1, S2, S3; // объявили 3 строки cin>>S1>>S2>>S3; ввести текст ‘Мама мыла раму’ (с произвольным количеством пробелов между словами), то в массив S1 будет записана строка "Мама", в S2 – "мыла", в S3 – "раму". Таким образом, организовать считывание всего файла по словам, можно следующим образом: string s; while (cin>>s) // Цикл пока считывание успешно { // Делаем необходимые действия } Если нужно считать строку со всеми пробелами, то необходимо использовать функцию getline следующим образом: string S; getline(cin, S); В данном случае если запустить эту программу и ввести строку "Мама мыла раму", то именно это значение и будет присвоено строке S. Считать же весь входной поток по строкам можно при помощи следующего кода: string S; while (getline(cin, S)) // Цикл пока считывание успешно { // Делаем необходимые действия Пример 1. Заменить во введенном с клавиатуры тексте все встречающиеся символы "n" на символ "b". Словесный алгоритм будет иметь вид: а) Формирование тела программы, объявление переменных; б) Ввод текста; в) Выяснение, не пустая ли строка; г) Если строка не пуста, то цикл, в котором сравнение очередного символа введенной строки с искомой переменной, с последующей заменой ее на определенный символ. На языке С++ данный алгоритм будет реализован следующей программой: #include <iostream> #include <string> using namespace std; #include <conio.h> void main(){ string s0, s1, s2; // Установка русской страницы setlocale(LC_ALL, "Russian"); // Чтение введенной с клавиатуры строки. cout<<"Введите текст для замены:"; getline(cin, s0); s1="n"; s2="b"; // Выясняем, не пустая ли строка. if (s0.empty()){ cout << "String is empty"<<"\n"; } else{ cout << "String isn't empty. Replacing..."<<"\n"; for (int i=0; i<s0.length(); i++) if (s0[i]==s1[0]) s0[i]=s2[0]; cout<<"Получили: "; cout<<s0; } _getch(); } Реализовав данную программу в интегрированной среде программирования, получим результирующее окно, представленное на рисунке 7.1. Рис. 7.1. Окно выполнения задачи Пример 2. Дан текст (допустим используются латинские символы), слова в котором будут разделяться пробелами. Требуется напечатать все слова с удвоенной буквой "n". Этапы решения задачи: Разобьем задачу на несколько блоков а) формирование тела программы, объявление переменных; б) ввод текста; в) определение начальных переменных и выяснение, не пустая ли строка; г) если строка не пустая, то организуем цикл пока она не кончится; д) сбрасываем flag и заполняем строку s1 пробелами; е) организуем цикл до окончания строки с текстом (выйдем, как только встретим пробел). Если очередной символ строки s0 не пробел, то копируем его в строку s1; ж) поиск в строке s1 (очередное слово) удвоенных букв "n" и печать найденного слова; з) удаление найденного слова из строки s0, включая последующий пробел. и) если текст не закончился возвращение к пункту (д). Реализуем эти блоки на языке С++: блок a) #include <iostream> #include <string> using namespace std; #include <conio.h> void main(){ string s0, s1, s2, pr; int j; bool flag; {} Назначение переменных: s0 – содержит введенный текст; s1 – хранит очередное слово текста; s1 – хранит очередное слово текста; s2 – хранит искомый в тексте символ; pr – хранит символ «пробела»; j – хранит размер найденного слова; flag – указывает, что данное слово искомое. блок б) setlocale(LC_ALL, "Russian"); // Чтение введенной с клавиатуры строки. cout<<"Введите текст для замены:"; getline(cin, s0); блок в) s2="n"; pr=" "; cout<<"Получили: "; // Выясняем, не пустая ли строка. if (s0.empty()) cout << "String is empty"<<"\n"; else {}; блок г) while (s0.length()!=0) {} блок д) flag=false; //Заполняем строку s1 пробелами j=0; s1.resize(1,' '); s1.resize(s0.size(),' '); блок е) for (int i=0; i<s0.length(); i++) {} if (s0[i]!=pr[0]) s1[i]=s0[i]; else break; j++; блок ж) // Проверяем, есть ли в очередном слове удвоенные буквы for (int i=1; i<s1.length(); i++) if ((s1[i]==s2[0])&&(s1[i-1]==s2[0])) flag=true; // Если есть, то выводим слово на экран if (flag) cout<<s1<<"\n"; блок з) s0.erase(0,j+1); Приведем программу целиком: #include <iostream> #include <string> using namespace std; #include <conio.h> void main(){ string s0, s1, s2, pr; int j; bool flag; setlocale(LC_ALL, "Russian"); // Чтение введенной с клавиатуры строки. cout<<"Введите текст для замены:"; getline(cin, s0); s2="n"; pr=" "; cout<<"Получили: "; // Выясняем, не пустая ли строка. if (s0.empty()) cout << "String is empty"<<"\n"; else{ // s0.length() - функция получения длины строки s0. while (s0.length()!=0) { flag=false; //Заполняем строку s1 пробелами j=0; s1.resize(1,' '); s1.resize(s0.size(),' '); for (int i=0; i<s0.length(); i++) { //Если очередной символ не пробел, //то копируем его в строку s1 if (s0[i]!=pr[0]) s1[i]=s0[i]; else break; j++; } // Проверяем, есть ли в очередном слове удвоенные буквы for (int i=1; i<s1.length(); i++) if ((s1[i]==s2[0])&&(s1[i-1]==s2[0])) flag=true; // Если есть, то выводим слово на экран if (flag) cout<<s1<<"\n"; //Изменяем длину строки на размер обработанного слова s0.erase(0,j+1); }; } _getch(); } Реализовав данную программу в интегрированной среде программирования, получим результирующее окно, представленное на рисунке 7.2. Рис. 7.2. Окно выполнения задачи В самом языке С++ нет типа данных «множество». Соответственно нет и операций над ними. Но в стандартной библиотеке шаблонов STL есть два подходящих шаблонных класса: set и multiset (множество и мультимножество). Второй отличается от первого тем, что элементы в нем могут повторяться. Такие операции как вставить, удалить, узнать размер, узнать есть ли такой элемент в множестве – там есть. Но необходимо самостоятельно реализовывать такие операции как найти пересечение, объединение, вычитание двух множеств (что является достаточно простым). Об STL можно почитать в книге: Николай Джосьютис. C++. Стандартная библиотека. Серия: Для профессионалов – СПб.: Питер, 2004 г., 736 стр. ISBN 5-94723-635-4. Контрольные вопросы Как описываются строковые переменные? Какая максимальная длина строки допустима в С++? Какие операции допустимы над строковыми данными? В чем отличие строковой переменной от массива символов? Какие стандартные процедуры и функции для работы со строками вы знаете? Что выведет функция Copy(x,Pos(' ',x)+1,18), если x='Сила есть - ума не надо'? Чему равно значение x[0] после присваивания x:='вопрос'? Задачи для индивидуального решения: 1. Дана строка, найти в ней удвоенные буквы. 2. Дана строка, содержащая математическую формулу. Проверить соблюдается ли в записи данной формулы баланс открывающихся и закрывающихся скобок. 3. Дана строка. Найти в ней количество слов. 4. Дана строка. Удалить все гласные в тексте. 5. Дана строка из слов, содержащих буквы и цифры. Слова разделены пробелами. Удалить из каждого слова цифры. Вариант 1 1. 2. Вариант 2 1. 2. Вариант 3 1. 2. Вариант 4 1. 2. Вариант 5 1. Найти самое длинное и самое короткое слово в заданном тексте. Дана строка. Заменить все гласные на символ ' * '. Дана строка. Если она представляет собой запись целого числа, то вывести 1, если вещественного (с дробной частью), то вывести 2, если строку нельзя преобразовать в число, то вывести 0. Дана строка. Утроить все символы в тексте. Дана строка. Найти количество слов 'krokodil'. Дана строка, содержащая полное имя файла. Выделить из строки название последнего каталога (без символа ‘\’). Если файл содержится в корневом каталоге, то вывести символ ‘\’. Вывести строку длины N (N-четное), которая состоит из чередующихся символов С1 и С2, начиная с С1. Написать программу, которая проверяет, является ли введенная с клавиатуры строка шестнадцатеричным числом и преобразует его в двоичное. Дана строка. Напечатать ее в обратном порядке. 2. Вариант 6 1. 2. Вариант 7 1. 2. Вариант 8 1. 2. Вариант 9 1. 2. Вариант 10 1. 2. Дана строка из строчных латинских букв. Напечатать все буквы, входящие в текст не менее двух pаз. Дана строка. Вывести текст по две буквы в столбик. Дана строка, состоящая из русских слов, разделенных пробелами (одним или несколькими). Вывести строку, содержащую эти же слова, но расположенные в обратном порядке и разделенные одним пробелом. Написать программу, которая проверяет, является ли введенная с клавиатуры строка целым числом. Удалить из слов с четной длиной все гласные, а из слов с нечетной длиной – все согласные. Дана строка из строчных латинских букв. Напечатать все буквы, входящие в текст по одному pазу. Дана строка. Удалить в тексте лишние пробелы между словами, оставив по одному. Дана строка. Удалить каждую вторую букву. Дана строка из слов, содержащих буквы и цифры. Вывести слова, упорядочив их по убыванию количества входивших в них цифр. Дан текст. Найти количество слов, заканчивающихся буквосочетанием 'kk'. Дана строка. Из заданного предложения удалить все слова, которые уже встречались в нем ранее. Рекомендуемая литература 1. Великович, Л.С. Программирование для начинающих / Л.С. Великович, М.С. Цветкова. – М.: БИНОМ, 2012. – 293 с. 2. Литвиненко, Н.А. Технология программирования на С++ / Н.А. Литвиненко. – СПб.: БХВ-Петербург, 2010 – 281 с. 3. Окулов, С.М. Основы программирования / С.М. Окулов. – М.: БИНОМ, 2012. – 340 с. 4. Пахомов, Б. С/С++ и MS Vusual C++ 2010 для начинающих / Б. Пахомов. – СПб.: БХВ-Петербург, 2011 – 726 с.