Инфоурок Информатика КонспектыЛекции по дисциплине "ОСНОВЫ АЛГОРИТМИЗАЦИИ И ПРОГРАММИРОВАНИЯ "

Лекции по дисциплине "ОСНОВЫ АЛГОРИТМИЗАЦИИ И ПРОГРАММИРОВАНИЯ "

Скачать материал

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

Лекция 1. Этапы разработки программ. Алго-ритмы и программы.doc Лекция 10 Основные принци-пы объектно-ориентированного программирования, создание и использование объектов..doc Лекция 11 Работа в среде BORLAND C++ BUILDER. Средства интегрированной среды разработки. Характеристика визуальных компонентов..doc Лекция 12 Составление и отладка программ с построением изображений. Анимация.doc Лекция 13 Создание многодокументных дополнений.doc Лекция 2 Лексика языка программирования С++ .doc Лекция 3 Скалярные типы данных. Целые типы. Вещественные типы. Переменные и константы. Объявления переменных.doc Лекция 4 Операции и выражения. Арифметические операции. Операции отношения. Логические операции. Операции присваивания. .doc Лекция 5 Программирование ветвлений. Программирование циклов .doc Лекция 6 Массивы. Одномерные и многомерные массивы. Сортировка массивов. Методы поиска элементов в массивах.doc Лекция 7 Указатели и массивы. Массивы указателей, динамические массивы. .doc Лекция 8 Определение функции.doc Лекция 9 Общая характеристика языков ассемблера. Работа с файлами. Использование ассемблерных вставок.doc

Выбранный для просмотра документ Лекция 1. Этапы разработки программ. Алго-ритмы и программы.doc

ТЕМА: Основы алгоритмизации и программирования. Этапы разработки программ. Алгоритмы. Понятие алгоритма. Формы записи алгоритмов. Базовые структуры алгоритмов. Данные. Понятие типа данных. Преобразование типов..

ТИП: лекция

ЦЕЛИ :

Учебная :

·       изучить особенности составления алгоритмов;

·       определить отличительные особенности построения блок схем;

Развивая :

·       • развивать логическое мышление , внимание , память ;

·       • развивать кругозор .

Воспитательная :

• развивать познавательный интерес к предмету.

Структура занятия

1 . Организационный момент ( 3 мин )

2 . Сообщения темы , цели занятия ( 5 мин )

3 . Актуализация знаний ( 15 мин )

4 . Выдача теоретического материала ( 30 мин )

5 . Проверка полученных знаний ( 10 мин )

6 . Подведение итогов , выставление оценок ( 5 мин )

7 . Выдача домашнего задания ( 2 мин )

Литература.

1.     Шилдт Г. С++: базовый курс, 3-е издание.: Пер. с англ.-М. : Издательский дом "Вильямс", 2010

2.     Архангельский А. Я. "Програмирование в C++ Builder". - М.: "Издательство Бином", 2003

3.     Деннис Ритчи "Язык программирования C. 2-е издание, переработанное и дополненное" Пер. с англ.-М. : Издательский дом "Вильямс", 2009

4.     Керниган Б. "Язык программирования Си"-Питер. Невский Диалект, 2009

5.     Вильямс А. Системное программирование в Windows 2000 для профессионалов - СПб: Питер, 2003. - 624 с.: ил.

6.     Юркин А. Задачник по программированию. — СПб.: Питер, 2002. — 192 с.

Вопрос актуализации знаний:

1.     Дайте определение языку программирования.

2.     Какие языки программирования вы знаете.

3.     Какие уровни языков программировании

План

1.     Структура программ для Microsoft Visual Studio

2.     Структура программы для C++ Builder.

3.     Синтаксис подключения заголовочных файлов:

4.     Опишите блоки из которых состоит программа на С++.

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

1.     Какие особенности написания программы для Microsoft Visual Studio?

2.     Какие особенности написания программы для C++ Builder?

3.     Как подключается заголовочный файл?

Алгоритм – последовательность чётко определенных действий, выполнение которых ведёт к решению задачи. Алгоритм, записанный на языке машины, есть программа решения задачи.

Алгоритм – это совокупность действий, приводящих к достижению результата за конечное число шагов.

Вообще говоря, первое определение не передает полноты смысла понятия алгоритм. Используемое слово "последовательность" сужает данное понятие, т.к. действия не обязательно должны следовать друг за другом – они могут повторяться или содержать условие.

Свойства алгоритмов:

1.                 Дискретность (от лат. discretus — разделенный, прерывистый) – это разбиение алгоритма на ряд отдельных законченных действий (шагов).

2.                 Детерминированность (от лат. determinate — определенность, точность) - любое действие алгоритма должно быть строго и недвусмысленно определено в каждом случае. Например, алгоритм проезда к другу, если к остановке подходят автобусы разных маршрутов, то в алгоритме должен быть указан конкретный номер маршрута 5. Кроме того, необходимо указать точное количество остановок, которое надо проехать, скажем, три.

3.                 Конечность – каждое действие в отдельности и алгоритм в целом должны иметь возможность завершения.

4.                 Массовость – один и тот же алгоритм можно использовать с разными исходными данными.

5.                 Результативность – алгоритм должен приводить к достоверному решению.

Основная цель алгоритмизации – составление алгоритмов для ЭВМ с дальнейшим решением задачи на ЭВМ.

Примеры алгоритма:

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

2.                 Каждый шофер должен знать правила дорожного движения. Правила дорожного движения однозначно регламентируют поведение каждого участника движения. Зная эти правила, шофер должен действовать по определенному алгоритму.

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

Существует несколько способов записи алгоритмов. На практике наиболее распространены следующие формы представления алгоритмов:

1.                 словесная (запись на естественном языке);

2.                 псевдокоды (полуформализованные описания алгоритмов на условном алгоритмическом языке, включающие в себя как элементы языка программирования, так и фразы естественного языка, общепринятые математические обозначения и др.);

3.                 графическая (изображения из графических символов – блок-схема);

4.                 программная (тексты на языках программирования – код программы).

Рассмотрим подробно каждый вариант записи алгоритмов на примере следующей задачи. Требуется найти частное двух чисел.

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

Пример словесной записи:

1.                 задать два числа, являющиеся делимым и делителем;

2.                 проверить, равняется ли делитель нулю;

3.                 если делитель не равен нулю, то найти частное, записать его в ответ;

4.                 если делитель равен нулю, то в ответ записать "нет решения".

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

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

Приведем основные управляющие структуры псевдокода в табл. 1.1.

Таблица 1.1. Базовые управляющие структуры псевдокода

Название структуры

Псевдокод

Присваивание

переменная = число

Ввод

ввод(переменная)

Вывод

вывод(переменная)

вывод("фраза")

Ветвление

если условие

то действие1

иначе действие2

Повторение

пока условие

начало пока

действие

конец пока

Пример псевдокода:

алг Нахождение частного двух чисел

начало

вывод ("задайте делимое и делитель")

ввод (делимое, делитель)

если делитель ≠ 0

то частное = делимое / делитель

   вывод(частное)

иначе вывод("нет решения")

кон алг Нахождение частного двух чисел

В данном примере используется три переменные: делимое, делитель и частное. Делимое и делитель задаются исполнителем произвольными числами. Частное считается лишь в том случае, если делитель не равен нулю.

Графическая реализация алгоритма представляет собой блок-схему. Блок-схема состоит из блоков определенной формы, соединенных стрелками. Ответ при этом получает человек, который выполняет команды согласно блок-схеме. Более подробно о блок-схемах будет рассказано в Лекции 2.

Программная реализация алгоритма – это компьютерная программа, написанная на каком-либо алгоритмическом языке программирования, например: С++, Pascal, Basic и т.д. Программа состоит из команд определенного языка программирования. Отметим, что одна и та же блок-схема может быть реализована на разных языках программирования. Ответ при этом получает ЭВМ, а не человек. Более подробно о составлении программ на языке программирования С++ смотреть Лекцию 3.

Различают три основных вида алгоритмов:

1.                 линейный алгоритм,

2.                 разветвляющийся алгоритм,

3.                 циклический алгоритм.

Линейный алгоритм – это алгоритм, в котором действия выполняются однократно и строго последовательно.

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

Словесный способ записи данного алгоритма:

1.                 выйти из университета на остановку;

2.                 подождать нужный автобус;

3.                 сесть на нужный автобус;

4.                 оплатить проезд;

5.                 выйти на требуемой остановке;

6.                 дойти до дома.

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

Разветвляющийся алгоритм – это алгоритм, в котором в зависимости от условия выполняется либо одна, либо другая последовательность действий.

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

Приведенный выше пример псевдокода по нахождению частного двух чисел также относится к разветвляющемуся алгоритму.

Циклический алгоритм – это алгоритм, команды которого повторяются некое количество раз подряд.

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

Блок-схема – это графическая реализация алгоритма.

Блок-схема представляет собой удобный и наглядный способ записи алгоритма.

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

Таблица 1. Виды блоков

Форма блока

Назначение блока

начало и конец блок-схемы

блок ввода данных

блок выполнения действия

блок условия

блок вывода данных

Любая команда алгоритма записывается в блок-схеме в виде графического элемента – блока, и дополняется словесным описанием. Блоки в блок-схемах соединяются линиями потока информации. Направление потока информации указывается стрелкой. В случае потока информации сверху вниз и слева направо стрелку ставить не обязательно. Блоки в блок-схеме имеют только один вход и один выход (за исключением логического блока – блока с условием).

Блок начала блок-схемы имеет один выход и не имеет входов, блок конца блок-схемы имеет один вход и не имеет выходов. Блок условия – единственный блок, имеющий два выхода, т.к. соответствует разветвляющемуся алгоритму. На одном выходе указывается "да", на другом – "нет". Все остальные блоки имеют один вход и один выход. Блок выполнения действия может содержать присвоение значения переменной (например "x=5") или вычисление (например "y=x-4").

Математические выражения и логические высказывания должны быть описаны математическим языком, т.к. блок-схема не должна иметь привязки к какому-то определенному языку программирования. Одна и таже блок-схема может быть реализована в программах на разных языках программирования. К примеру, функция в блок-схеме будет выглядеть таким образом: y=x^2, а не таким образом: y=x ^\wedge 2.

Все три вида алгоритмов реализуются в блок-схеме названными выше типами блоков. К примеру, в линейном алгоритме могут присутствовать все блоки, кроме блока условия. В разветвляющемся и циклическом алгоритмах могут быть использованы все названные виды блоков, но обязательным является блок условия. Внутри блока условия записывается условие, про которое можно однозначно ответить, истинно оно или ложно Если условие истинно, то выполняются действия, соответствующие стрелке "да", иначе стрелке "нет".

Занятие 2. Графическая реализация линейного алгоритма

Приведем простейшие примеры, соответствующие линейному алгоритму.

Пример 1. Вася хочет позвонить Пете по городскому телефону. Необходимо составить блок-схему, описывающую порядок действий Васи.

Решение. Чтобы позвонить по городскому телефону, нужно знать номер Пети. Значит, сначала надо найти номер телефона Пети, набрать его и поговорить с Петей. На этом цель Васи (поговорить с Петей по телефону) будет достигнута. Результат блок схемы представлен на рис. 2.1.

Блок-схема для примера 1

Рис 1. Блок-схема для примера 1

Пример 2. Ученику требуется купить учебник. Составить блок-схему, описывающую порядок действий ученика.

Решение. Сначала ученику нужно взять деньги, потом прийти в книжный магазин и заплатить за учебник. На этом цель (покупка учебника) будет достигнута. Результат блок схемы представлен на рис.2.

Блок-схема для примера 2

Рис. 2. Блок-схема для примера 2

Пример 3. Даны числа a=2, b=7. Вычислить сумму Sи разность Rчисел aи b.

Решение. Сначала следует задать значения для чисел aи b, согласно условиям задачи. После этого их уже можно будет использовать в расчетах для получения суммы и разности по формулам: S=a+b, R=a-b. Полученные значения суммы и разности нужно будет показать на экране, и мы используем блок вывода данных. Если не выводить данные на экран, то пользователь нашего алгоритма не узнает, какие получились значения суммы и разности. Результат блок схемы представлен на рис. 3.

Блок-схема для примера 3: а) в каждом блоке по одному действию, б) действия объединены по смыслу операции

Рис. 2.3. Блок-схема для примера 3: а) в каждом блоке по одному действию, б) действия объединены по смыслу операции

В блок-схеме на рис. 3а каждое действие расположено в отдельном блоке. В блок-схеме рис. 3б объединены между собой схожие по смыслу операции. В дальнейшем мы будем объединять некоторые действия в один блок. Это очень удобно и визуально упрощает чтение блок-схемы.

Занятие 3. Графическая реализация разветвляющегося алгоритма

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

Использование блока условия в общем виде


Рис. 4. Использование блока условия в общем виде

Внутри блока условия записывается условие. Если данное условие верно, то выполняются блоки, идущие по стрелке "да", т.е. "Набор действий 1". Если условие оказывается неверным, т.е. ложным, то выполняются блоки, идущие по стрелке "нет", а именно "Набор действий 2". Разветвление заканчивается, когда обе стрелки ("да" и "нет") соединяются. На рис. 2.5 представлен еще один вариант использования блока условия. Бывают задачи, в которых, исходя из условия, необходимо либо выполнить действие, либо пропустить его. Если условие верно выполняется, то следуют блоки, соответствующие стрелке "да", т.е. "Набор действий 1". Если же условие оказывается ложным, то следует перейти по стрелке "нет". Т.к. стрелке "нет" не соответствует ни одного блока с действием, то ни одного действия не будет выполнено. Т.е. получается, что мы пропустили и не выполнили "Набор действий 1".

Вариант использования блока условия

Рис. 5. Вариант использования блока условия

В разветвляющемся алгоритме возможна запись сразу нескольких условий, которые могут объединяться союзом "ИЛИ" или пересекаться союзом "И". Рассмотрим случай двух условий: "условие 1" и "условие 2".

Если необходимо, чтобы оба условия были верными одновременно, то следует использовать логическое пересечение "И":

"условие 1 и условие 2".

Если достаточно, чтобы только одно условие выполнялось – либо первое, либо второе, то следует использовать логическое объединение "ИЛИ":

"условие 1 ИЛИ условие 2".

Приведем простейшие примеры, соответствующие разветвляющемуся алгоритму.

Пример 4. Джон звонит Полу по городскому телефону, но трубку может взять не только Пол. Составить блок-схему, описывающую действия Джона в этом случае.

Решение. В отличие от примера 1, здесь присутствует условие – Пол ли взял трубку телефона. На данное условие можно однозначно ответить: "да", Пол, или "нет", кто-то другой. Если трубку взял Пол, то Джону нужно с ним поговорить, и цель будет достигнута. Если трубку взял кто-то другой, то необходимо позвать Пола к телефону, поговорить с ним, и цель также будет достигнута. Третьего варианта, например, "не туда попали" или "его нет дома" мы не рассматриваем. Результат блок-схемы представлен на рис. 2.6.

Блок-схема для примера 4

Рис. 6. Блок-схема для примера 4

Пример 5. Ученику требуется купить учебник. В магазине в наличие оказался нужный учебник в жесткой и мягкой обложке. Составить блок-схему, описывающую действия ученика.

Решение. В данном примере присутствует условие: "Нужна жесткая обложка".

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

Если ученик не соглашается с данным условием, то будет выполняться действие, соответствующее стрелке "нет", и в этом случае ученик купит учебник в мягкой обложке.

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

Результат блок схемы представлен на рис. 7.

Блок-схема для примера 5

Рис. 7. Блок-схема для примера 5

Пример 6. Даны числа a=2, b=7. Вычислить сумму Sи разность Rчисел aи b. Сравнить полученные значения Sи Rи указать большее из них.

Решение. Как и в примере 3, сначала необходимо задать значения aи b. Затем рассчитать сумму и разность по формулам: S=a+b, R=a-b, и вывести полученные числа на экран (блок вывода данных). Когда значения Sи Rбудут получены, следует сравнить их между собой. Условие запишется в виде: S>R. Если полученная сумма Sбудет больше разности R, то мы пойдем по стрелке "да" и выведем фразу "max S". Если же условие окажется ложным (т.е. S<R), то пойдем по стрелке "нет" и выведем фразу "max R". Результат блок схемы представлен на рис. 2.8.

Блок-схема для примера 6

Рис. 8. Блок-схема для примера 6

Занятие 4. Графическая реализация циклического алгоритма

В рассмотрении циклического алгоритма следует выделить несколько понятий.

Тело цикла – это набор инструкций, предназначенный для многократного выполнения.

Итерация – это единичное выполнение тела цикла.

Переменная цикла – это величина, изменяющаяся на каждой итерации цикла.

Каждый цикл должен содержать следующие необходимые элементы:

первоначальное задание переменной цикла,

проверку условия,

выполнение тела цикла,

изменение переменной цикла.

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

Циклический алгоритм с предусловием в общем виде

Рис. 9. Циклический алгоритм с предусловием в общем виде

В цикле с постусловием сначала выполняется тело цикла, а потом проверяется условие. Циклический алгоритм с постусловием представлен на рис. 10.

Циклический алгоритм с постусловием в общем виде

Рис. 2.10. Циклический алгоритм с постусловием в общем виде

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

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

Приведем простейшие примеры, соответствующие циклическому алгоритму.

Пример 7. Вася звонит Пете, но у Пети может быть занята линия. Составить блок-схему действий Васи в этом случае.

Решение. Когда телефонная линия занята, то необходимо снова и снова набирать номер, пока Петя не закончит предыдущий разговор, и телефонная линия не окажется вновь свободной. Блок-схема представлена на рис. 11.

Блок-схема для примера 7

Рис. 11. Блок-схема для примера 7

Здесь тело цикла состоит из одного действия "Набрать номер Пети", т.к. именно это действие следует повторять, пока линия будет занята. Под итерацией цикла понимается очередная попытка дозвониться до Пети. Как таковой переменной цикла здесь нет, т.к. ситуация взята из жизни. Выход из цикла происходит в тот момент, когда условие "У Пети занято" стало неверным, т.е. телефонная линия свободна – действительно, нет необходимости больше набирать номер Пети. В данном примере применен цикл с постусловием, т.к. сначала необходимо набрать номер Пети, ведь иначе мы не можем ответить на вопрос – занята ли линия у Пети.

Пример 8. Ученику требуется купить учебник. Составить блок-схему, описывающую действия ученика в случае, если учебника нет в ряде магазинов.

Решение. Действия ученика в данном примере очевидны: когда он приходит в первый и любой последующий магазины, то возможны два варианта – учебник имеется в наличии или учебника нет в продаже. Если учебника нет в продаже, то ученику следует пойти в другой книжный магазин и спросить данный учебник, и т.д. пока учебник не будет куплен, т.к. перед учеником стоит конечная цель – купить учебник. Мы будем использовать цикл с предусловием, т.к. сначала требуется найти магазин, имеющий в наличии данный учебник. Цикл будет выполняться, пока условие "В данном магазине нет учебника" будет верным, а выход из цикла осуществится, когда условие станет ложным, т.е. когда ученик придет в магазин, в котором есть данный учебник. Действительно, в этом случае ученик купит нужный ему учебник и не будет больше искать книжные магазины. Результат блок-схемы представлен на рис.12.

Блок-схема для примера 8

Рис. 12. Блок-схема для примера 8

Здесь тело цикла состоит из одного действия "Найти другой книжный магазин". Переменной цикла в явном виде нет, но можно подразумевать номер магазина, в который пришел ученик в очередной раз. Как любой другой цикл с предусловием, данный цикл может ни разу не выполниться (не иметь итераций), если в первом же магазине окажется нужный учебник.

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

Пример 9. Даны числа a, b. Известно, что число аменяется от -10 до 10 с шагом 5, b=7и не изменяется. Вычислить сумму Sи разность Rчисел aи bдля всех значений aи b.

Решение. В отличие от примеров 3 и 6 здесь число аменяется от -10 до 10 с шагом 5. Это означает, что число аявляется переменной цикла. Сначала аравно -10 – это первоначальное задание переменной цикла. Далее абудет изменяться с шагом 5, и т.д. пока не будет достигнуто значение 10 – это соответствует изменению переменной цикла. Итерации надо повторять, пока выполняется условие "a\le 10". Итак, абудет принимать следующие значения: -10, -5, 0, 5, 10. Число bне будет являться переменной цикла, т.к. b=7и не изменяется по условию задачи. Результат блок-схемы (с предусловием) представлен на рис. 2.13.

Блок-схема для примера 9 (с предусловием)

Рис. 13. Блок-схема для примера 9 (с предусловием)

Тело цикла состоит из нескольких действий: вычисление суммы, вычисление разности и вывод полученных данных на экран. Таким образом, у нас получится несколько значений сумм и разностей, т.к. аизменяется. Количество сумм и количество разностей совпадет с количеством различных значений а, т.е. пять.

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

Приведем блок-схему, использующую цикл с постусловием, на рис. 14.

Блок-схема для примера 9 (с постусловием)

Рис. 14. Блок-схема для примера 9 (с постусловием)

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

Блок-схема с ветвлением для примера 9: а) с предусловием,    б) с постусловием

Рис. 15. Блок-схема с ветвлением для примера 9: а) с предусловием, б) с постусловием

Занятие 5. Выполнение блок-схем

Блок-схема сама по себе не содержит ответа. Чтобы получить результат, нужно выполнить блок-схему.

Выполнение блок-схемы – это прохождение всех действий блок-схемы согласно алгоритму от блока Начало до блока Конец для получения результата.

Если блок-схема составлена корректно, то, выполнив ее, человек получит ответ к своей задаче. Если же при составлении блок-схемы были допущены ошибки, то исполнитель либо вообще не дойдет до блока Конец, либо получит неверный ответ.

Для выполнения нам понадобится поле для расчетов (аналог "оперативной памяти") и поле для вывода результата (аналог экрана для вывода данных). Экран будем показывать несколько раз в зависимости от вывода новых данных на экране.

Выполнение блок-схемы для примера 3. Даны числа a=2, b=7. Вычислить сумму Sи разность Rчисел aи b.

Выполнение блок-схемы приведем в табл.2.

Таблица 2.2. Выполнение блок-схемы для примера 3

Расчеты:

Начало

a=2

b=7

S=a+b={подставляем значения a и b}=2+7=9

R=a-b={подставляем значения a и b}=2-7=-5

Выводим на экран S=9, R=-5:

                                              

Вывод данных (экран)

S=9

R=-5

                                                                 

Конец.

Выполнение блок-схемы для примера 6. Даны числа a=2, b=7. Вычислить сумму Sи разность Rчисел aи b. Сравнить полученные значения Sи Rи указать большее из них.

Выполнение блок-схемы приведем в табл. 2.3.

Таблица.3. Выполнение блок-схемы для примера 6

Расчеты:

Начало

a=2

b=7

S=a+b=2+7=9

R=a-b=2-7=-5

Выводим на экран S=9, R=-5:

                                     

Вывод данных (экран)

S=9

R=-5

                                                        

S>R   9>-5   да, верно

Выводим на экран "Max S":

                                     

Вывод данных (экран)

S=9

R=-5

Max S

                                                        

Конец.

Выполнение блок-схемы для примера 9. Даны числа a, b. Известно, что число аменяется от -10 до 10 с шагом 5, b=7и не изменяется. Вычислить сумму Sи разность Rчисел aи bдля всех значений aи b.

Выполнение блок-схемы с предусловием приведем в табл. 2.4.

Таблица 4. Выполнение блок-схемы с предусловием для примера 9

Расчеты:

Начало

b=7

a=-10

a≤10   -10≤10   да, верно

S=a+b=-10+7=-3

R=a-b=-10-7=-17

Вывод S, R

                                              

Экран

S=-3   R=-17

a=a+5=-10+5=-5

{Идем по стрелке вверх}

a≤10   -5≤10   да, верно

S=a+b=-5+7=2

R=a-b=-5-7=-12

Вывод S, R

                                     

Экран

S=-3   R=-17

S=2   R=-12

                                                        

a=a+5=-5+5=0

{Идем по стрелке вверх}

a≤10   0≤10   да, верно

S=a+b=0+7=7

R=a-b=0-7=-7

Вывод S, R

Экран

S=-3   R=-17

S=2   R=-12

S=7   R=-7

                                                        

a=a+5=0+5=5

{Идем по стрелке вверх}

a≤10   5≤10   да, верно

S=a+b=5+7=12

R=a-b=5-7=-2

Вывод S, R

                                     

Экран

S=-3   R=-17

S=2   R=-12

S=7   R=-7

S=12   R=-2

                                                        

a=a+5=5+5=10

{Идем по стрелке вверх}

a≤10   10≤10   да, верно

S=a+b=10+7=17

R=a-b=10-7=3

Вывод S, R

                                     

Экран

S=-3   R=-17

S=2   R=-12

S=7   R=-7

S=12   R=-2

S=17   R=3

                                                        

a=a+5=10+5=15

{Идем по стрелке вверх}

a≤10   15≤10   нет, ложно {выходим из цикла}

Конец.

                                     

Выполнение блок-схемы с постусловием приведем в табл. 5.

Таблица 5. Выполнение блок-схемы с постусловием для примера 9

Расчеты:

Начало

b=7

a=-10

S=a+b=-10+7=-3

R=a-b=-10-7=-17

Вывод S, R

                                              

Экран

S=-3   R=-17

a=a+5=-10+5=-5

a≤10   -5≤10   да, верно

{Идем по стрелке вверх}

S=a+b=-5+7=2

R=a-b=-5-7=-12

Вывод S, R

                                     

Экран

S=-3   R=-17

S=2   R=-12

                                                        

a=a+5=-5+5=0

a≤10   0≤10   да, верно

{Идем по стрелке вверх}

S=a+b=0+7=7

R=a-b=0-7=-7

Вывод S, R

Экран

S=-3   R=-17

S=2   R=-12

S=7   R=-7

                                                        

a=a+5=0+5=5

a≤10   5≤10   да, верно

{Идем по стрелке вверх}

S=a+b=5+7=12

R=a-b=5-7=-2

Вывод S, R

                                     

Экран

S=-3   R=-17

S=2   R=-12

S=7   R=-7

S=12   R=-2

                                                        

a=a+5=5+5=10

a≤10   10≤10   да, верно

{Идем по стрелке вверх}

S=a+b=10+7=17

R=a-b=10-7=3

Вывод S, R

                                     

Экран

S=-3   R=-17

S=2   R=-12

S=7   R=-7

S=12   R=-2

S=17   R=3

                                                        

a=a+5=10+5=15

a≤10   15≤10   нет, ложно {выходим из цикла}

Конец.

                                     

Пример 10. Даны числа a, b. Известно, что число аменяется от -10 до 10 с шагом 5, b=7и не изменяется. Вычислить сумму Sи разность Rи сравнить полученные значения суммы и разности для всех значений aи b.

Выполнение блок-схемы с предусловием приведем в табл. 2.6.

Таблица 2.6. Выполнение блок-схемы с предусловием для примера 10

Расчеты:

Начало

b=7

a=-10

a≤10   -10≤10   да, верно

S=a+b=-10+7=-3

R=a-b=-10-7=-17

Вывод S, R

S>R   -3>-17   да, верно

Вывод "Max S"

                                              

Вывод данных (экран)

S=-3   R=-17   Max S

a=a+5=-10+5=-5

{Идем по стрелке вверх}

a≤10   -5≤10   да, верно

S=a+b=-5+7=2

R=a-b=-5-7=-12

Вывод S, R

S>R   2>-12   да, верно

Вывод "Max S"

                                     

Вывод данных (экран)

S=-3   R=-17   Max S

S=2   R=-12   Max S

                                                        

a=a+5=-5+5=0

{Идем по стрелке вверх}

a≤10   0≤10   да, верно

S=a+b=0+7=7

R=a-b=0-7=-7

Вывод S, R

S>R   7>-7   да, верно

Вывод "Max S"

Вывод данных (экран)

S=-3   R=-17   Max S

S=2   R=-12   Max S

S=7   R=-7   Max S

                                                        

a=a+5=0+5=5

a≤10   5≤10   да, верно

{Идем по стрелке вверх}

S=a+b=5+7=12

R=a-b=5-7=-2

Вывод S, R

S>R   12>-2   да, верно

Вывод "Max S"

                                     

Вывод данных (экран)

S=-3   R=-17   Max S

S=2   R=-12   Max S

S=7   R=-7   Max S

S=12   R=-2   Max S

                                                        

a=a+5=5+5=10

{Идем по стрелке вверх}

a≤10   10≤10   да, верно

S=a+b=10+7=17

R=a-b=10-7=3

Вывод S, R

S>R   17>3   да, верно

Вывод "Max S"

                                     

Вывод данных (экран)

S=-3   R=-17   Max S

S=2   R=-12   Max S

S=7   R=-7   Max S

S=12   R=-2   Max S

S=17   R=3   Max S

                                                        

a=a+5=10+5=15

{Идем по стрелке вверх}

a≤10   15≤10   нет, ложно {выходим из цикла}

Конец.

                                     

В процессе составления блок-схемы важно "ходить" по стрелкам из блока в блок, следить, чтобы не получалось "тупиковых ситуаций". Такая ситуация возникает, если составитель блок-схемы не нарисовал стрелку из блока. Также частой ошибкой является замыкание стрелки не в тот блок, например при реализации циклического алгоритма.

Краткие итоги

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

Вопросы

1.     Что такое блок-схема?

2.     Какие типы блоков бывают?

3.     Какие блоки используются при реализации линейного, разветвляющегося, циклического алгоритмов?

4.     Можно ли составить разные варианты блок-схем для одной и той же задачи?

5.     Какие виды циклического алгоритма бывают?

6.     Какие пункты должны присутствовать в любом цикле?

7.     Что такое выполнение блок-схемы?

8.     Для чего следует выполнять блок-схему?

Упражнения

1.     Составьте блок-схемы для задачи по походу в магазин за яблоками. Используйте линейный, разветвляющийся и циклический алгоритмы.

2.     Составьте блок-схему для нахождения корней квадратного уравнения через дискриминант. Используйте разветвляющийся алгоритм. Получите ответ, выполнив блок-схему.

3.     Составьте блок-схемы для вывода на экран целых чисел от 1 до 10. Используйте цикл с предусловием, с постусловием. Выполните блок-схемы.

Просмотрено: 0%
Просмотрено: 0%
Скачать материал
Скачать материал "Лекции по дисциплине "ОСНОВЫ АЛГОРИТМИЗАЦИИ И ПРОГРАММИРОВАНИЯ ""

Методические разработки к Вашему уроку:

Получите новую специальность за 2 месяца

Инструктор по волейболу

Получите профессию

Интернет-маркетолог

за 6 месяцев

Пройти курс

Рабочие листы
к вашим урокам

Скачать

Выбранный для просмотра документ Лекция 10 Основные принци-пы объектно-ориентированного программирования, создание и использование объектов..doc

ТЕМА Основные принципы объектно-ориентированного программирования, создание и использование объектов.

ТИП: комбинированное занятие.

ЦЕЛИ :

Учебная :

·        изучить способы задания класса

·        Научиться использовать классы в программах

Развивая :

·        • развивать логическое мышление , внимание , память ;

·        • развивать кругозор .

Воспитательная :

·        • развивать познавательный интерес к предмету.

·       Структура занятия

·       1 . Организационный момент ( 3 мин )

·       2 . Сообщения темы , цели занятия ( 5 мин )

·       3 . Актуализация знаний ( 10 мин )

·       4 . Выдача теоретического материала ( 20 мин )

·       5 . Проверка полученных знаний на практике ( 35 мин )

·       6 . Подведение итогов , выставление оценок ( 5 мин )

·       7 . Выдача домашнего задания ( 2 мин )

Литература.

1.     Шилдт Г. С++: базовый курс, 3-е издание.: Пер. с англ.-М. : Издательский дом "Вильямс", 2010

2.     Архангельский А. Я. "Програмирование в C++ Builder". - М.: "Издательство Бином", 2003

3.     Деннис Ритчи "Язык программирования C. 2-е издание, переработанное и дополненное" Пер. с англ.-М. : Издательский дом "Вильямс", 2009

4.     Керниган Б. "Язык программирования Си"-Питер. Невский Диалект, 2009

5.     Вильямс А. Системное программирование в Windows 2000 для профессионалов - СПб: Питер, 2003. - 624 с.: ил.

6.     Юркин А. Задачник по программированию. — СПб.: Питер, 2002. — 192 с.

Вопрос актуализации знаний:

1.     Дайте определение структуре?

2.     Дайте определение типа.

3.     Как задаются структуры

4.     Какие типы данных Вы знаете?

5.      Перечислите и приведите примеры простых типов данных.

6.      Перечислите сложные типы данных.

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

1.     Основные типы наследования в классах

2.     Правильная конструкция определения класса в С++?

3.      Какие функции есть у любого класса??

4.     Назовите преимущества классов?

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

6.     Что такое деструктор?

7.     Что такое объект?

8.     Что такое класс?

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

 

План.

 
  1. Основные понятия
  2. Модификаторы доступа public и private
  3. Программа учета успеваемости студентов
  4. Отделение данных от логики
  5. Создание объекта через указатель
  6. Конструктор и деструктор класса

Основные понятия

Классы в программировании состоят из свойств и методов. Свойства — это любые данные, которыми можно характеризовать объект класса. В нашем случае, объектом класса является студент, а его свойствами — имя, фамилия, оценки и средний балл.

У каждого студента есть имя — name и фамилия last_name . Также, у него есть промежуточные оценки за весь семестр. Эти оценки мы будем записывать в целочисленный массив из пяти элементов. После того, как все пять оценок будут проставлены, определим средний балл успеваемости студента за весь семестр — свойство average_ball.

Методы — это функции, которые могут выполнять какие-либо действия над данными (свойствами) класса. Добавим в наш класс функцию calculate_average_ball(), которая будет определять средний балл успеваемости ученика.

  • Методы класса — это его функции.
  • Свойства класса — его переменные.
class Students {
    public:
        // Функция, считающая средний балл
        void calculate_average_ball()
        {
            int sum = 0; // Сумма всех оценок
            for (int i = 0; i < 5; ++i) {
                sum += scores[i];
            }
            // считаем среднее арифметическое
            average_ball = sum / 5.0;
        }
 
        // Имя студента
        std::string name;
        // Фамилия
        std::string last_name;
        // Пять промежуточных оценок студента
        int scores[5];
 
    private:
        // Итоговая оценка за семестр
        float average_ball;
};

Функция calculate_average_ball() просто делит сумму всех промежуточных оценок на их количество.

Модификаторы доступа public и private

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

Закрытые данные класса размещаются после модификатора доступа private. Если отсутствует модификатор public, то все функции и переменные, по умолчанию являются закрытыми (как в первом примере).

Обычно, приватными делают все свойства класса, а публичными — его методы. Все действия с закрытыми свойствами класса реализуются через его методы. Рассмотрим следующий код.

class Students {
    public:
        // Установка среднего балла
        void set_average_ball(float ball)
        {
            average_ball = ball;
        }
        // Получение среднего балла
        float get_average_ball()
        {
            return average_ball;
        }
        std::string name;
        std::string last_name;
        int scores[5];
 
    private:
        float average_ball;
};

Мы не можем напрямую обращаться к закрытым данными класса. Работать с этими данными можно только посредством методов этого класса. В примере выше, мы используем функцию get_average_ball() для получения средней оценки студента, и set_average_ball() для выставления этой оценки.

Функция set_average_ball() принимает средний балл в качестве параметра и присваивает его значение закрытой переменной average_ball. Функция get_average_ball() просто возвращает значение этой переменной.

Программа учета успеваемости студентов

Создадим программу, которая будет заниматься учетом успеваемости студентов в группе. Создайте заголовочный файл students.h, в котором будет находиться класс Students.

/* students.h */
#include <string>
 
class Students {
    public:
        // Установка имени студента
        void set_name(std::string student_name)
        {
            name = student_name;
        }
        // Получение имени студента
        std::string get_name()
        {
            return name;
        }
        // Установка фамилии студента
        void set_last_name(std::string student_last_name)
        {
            last_name = student_last_name;
        }
        // Получение фамилии студента
        std::string get_last_name()
        {
            return last_name;
        }
        // Установка промежуточных оценок
        void set_scores(int student_scores[])
        {
            for (int i = 0; i < 5; ++i) {
                scores[i] = student_scores[i];
            }
        }
        // Установка среднего балла
        void set_average_ball(float ball)
        {
            average_ball = ball;
        }
        // Получение среднего балла
        float get_average_ball()
        {
            return average_ball;
        }
 
    private:
        // Промежуточные оценки
        int scores[5];
        // Средний балл
        float average_ball; 
        // Имя
        std::string name;
        // Фамилия
        std::string last_name;
};

Мы добавили в наш класс новые методы, а также сделали приватными все его свойства. Функция set_name() сохраняет имя студента в переменной name, а get_name() возвращает значение этой переменной. Принцип работы функций set_last_name() и get_last_name() аналогичен.

Функция set_scores() принимает массив с промежуточными оценками и сохраняет их в приватную переменную int scores[5].

Теперь создайте файл main.cpp со следующим содержимым.

/* main.cpp */
#include <iostream>
#include "students.h"
 
int main()
{
    // Создание объекта класса Student
    Students student;
 
    std::string name;
    std::string last_name;
 
    // Ввод имени с клавиатуры
    std::cout << "Name: ";
    getline(std::cin, name);
 
    // Ввод фамилии
    std::cout << "Last name: ";
    getline(std::cin, last_name);
 
    // Сохранение имени и фамилии в объект класса Students
    student.set_name(name);
    student.set_last_name(last_name);
 
    // Оценки
    int scores[5];
    // Сумма всех оценок
    int sum = 0;
 
    // Ввод промежуточных оценок 
    for (int i = 0; i < 5; ++i) {
        std::cout << "Score " << i+1 << ": ";
        std::cin >> scores[i];
        // суммирование
        sum += scores[i];
    }
 
    // Сохраняем промежуточные оценки в объект класса Student
    student.set_scores(scores);
    // Считаем средний балл
    float average_ball = sum / 5.0;
    // Сохраняем средний балл в объект класса Students
    student.set_average_ball(average_ball);
    // Выводим данные по студенту
    std::cout << "Average ball for " << student.get_name() << " "
         << student.get_last_name() << " is "
         << student.get_average_ball() << std::endl;
 
    return 0;
}

В самом начале программы создается объект класса Students. Дело в том, что сам класс является только описанием его объекта. Класс Students является описанием любого из студентов, у которого есть имя, фамилия и возможность получения оценок.

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

После создания объекта student, мы вводим с клавиатуры фамилию, имя и промежуточные оценки для конкретного ученика. Пускай это будет Вася Пупкин, у которого есть пять оценок за семестр — две тройки, две четверки и одна пятерка.

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

Скомпилируйте и запустите программу.

Пример работы программы Students

Отделение данных от логики

Вынесем реализацию всех методов класса в отдельный файл students.cpp.

/* students.cpp */
#include <string>
#include "students.h"
 
// Установка имени студента
void Students::set_name(std::string student_name)
{
    Students::name = student_name;
}
 
// Получение имени студента
std::string Students::get_name()
{
    return Students::name;
}
 
// Установка фамилии студента
void Students::set_last_name(std::string student_last_name)
{
    Students::last_name = student_last_name;
}
 
// Получение фамилии студента
std::string Students::get_last_name()
{
    return Students::last_name;
}
 
// Установка промежуточных оценок
void Students::set_scores(int scores[])
{
    for (int i = 0; i < 5; ++i) {
        Students::scores[i] = scores[i];
    }
}
 
// Установка среднего балла
void Students::set_average_ball(float ball)
{
    Students::average_ball = ball;
}
 
// Получение среднего балла
float Students::get_average_ball()
{
    return Students::average_ball;
}

А в заголовочном файле students.h оставим только прототипы этих методов.

/* students.h */
#pragma once /* Защита от двойного подключения заголовочного файла */
#include <string>
 
class Students {
    public:
        // Установка имени студента
        void set_name(std::string);
        // Получение имени студента
        std::string get_name();
        // Установка фамилии студента
        void set_last_name(std::string);
        // Получение фамилии студента
        std::string get_last_name();
        // Установка промежуточных оценок
        void set_scores(int []);
        // Установка среднего балла
        void set_average_ball(float);
        // Получение среднего балла
        float get_average_ball();
 
    private:
        // Промежуточные оценки
        int scores[5];
        // Средний балл
        float average_ball;
        // Имя
        std::string name;
        // Фамилия
        std::string last_name;
};

Такой подход называется абстракцией данных — одного из фундаментальных принципов объектно-ориентированного программирования. К примеру, если кто-то другой захочет использовать наш класс в своем коде, ему не обязательно знать, как именно высчитывается средний балл. Он просто будет использовать функцию calculate_average_ball() из второго примера, не вникая в алгоритм ее работы.

Над крупными проектами обычно работает несколько программистов. Каждый из них занимается написанием определенной части продукта. В таких масштабах кода, одному человеку практически нереально запомнить, как работает каждая из внутренних функций проекта. В нашей программе, мы используем оператор потокового вывода cout, не задумываясь о том, как он реализован на низком уровне. Кроме того, отделение данных от логики является хорошим тоном программирования.

В начале обучения мы говорили о пространствах имен (namespaces). Каждый класс в C++ использует свое пространство имен. Это сделано для того, чтобы избежать конфликтов при именовании переменных и функций. В файле students.cpp мы используем оператор принадлежности :: перед именем каждой функции. Это делается для того, чтобы указать компилятору, что эти функции принадлежат классу Students.

Создание объекта через указатель

При создании объекта, лучше не копировать память для него, а выделять ее в в куче с помощью указателя. И освобождать ее после того, как мы закончили работу с объектом. Реализуем это в нашей программе, немного изменив содержимое файла main.cpp.

/* main.cpp */
#include <iostream>
#include "students.h"
 
int main()
{
    // Выделение памяти для объекта Students
    Students *student = new Students;
 
    std::string name;
    std::string last_name;
 
    // Ввод имени с клавиатуры
    std::cout << "Name: ";
    getline(std::cin, name);
 
    // Ввод фамилии
    std::cout << "Last name: ";
    getline(std::cin, last_name);
 
    // Сохранение имени и фамилии в объект класса Students
    student->set_name(name);
    student->set_last_name(last_name);
 
    // Оценки
    int scores[5];
    // Сумма всех оценок
    int sum = 0;
 
    // Ввод промежуточных оценок 
    for (int i = 0; i < 5; ++i) {
        std::cout << "Score " << i+1 << ": ";
        std::cin >> scores[i];
        // суммирование
        sum += scores[i];
    }
    // Сохраняем промежуточные оценки в объект класса Student
    student->set_scores(scores);
 
    // Считаем средний балл
    float average_ball = sum / 5.0;
    // Сохраняем средний балл в объект класса Students
    student->set_average_ball(average_ball);
    // Выводим данные по студенту
    std::cout << "Average ball for " << student->get_name() << " "
         << student->get_last_name() << " is "
         << student->get_average_ball() << std::endl;
    // Удаление объекта student из памяти
    delete student; 
    return 0;
}

При создании статического объекта, для доступа к его методам и свойствам, используют операция прямого обращения — «.» (символ точки). Если же память для объекта выделяется посредством указателя, то для доступа к его методам и свойствам используется оператор косвенного обращения — «->».

Конструктор и деструктор класса

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

class Students {
    public:
        // Конструктор класса Students
        Students(int default_score)
        {
            for (int i = 0; i < 5; ++i) {
                scores[i] = default_score;
            }
        }
 
    private:
        int scores[5];
};
 
int main()
{
    // Передаем двойку в конструктор
    Students *student = new Students(2);
    return 0;
}

Мы можем исправить двойки, если ученик будет хорошо себя вести, и вовремя сдавать домашние задания. А на «нет» и суда нет :-)

Деструктор класса вызывается при уничтожении объекта. Имя деструктора аналогично имени конструктора, только в начале ставится знак тильды ~. Деструктор не имеет входных параметров.

#include <iostream>
 
class Students {
    public:
        // Деструктор
        ~Students()
        {
            std::cout << "Memory has been cleaned. Good bye." << std::endl;
        }
};
 
int main()
{
    Students *student = new Students;
    // Уничтожение объекта
    delete student;
    return 0;
}

Пример работы деструктора

 

Просмотрено: 0%
Просмотрено: 0%
Скачать материал
Скачать материал "Лекции по дисциплине "ОСНОВЫ АЛГОРИТМИЗАЦИИ И ПРОГРАММИРОВАНИЯ ""

Получите профессию

Бухгалтер

за 6 месяцев

Пройти курс

Рабочие листы
к вашим урокам

Скачать

Выбранный для просмотра документ Лекция 11 Работа в среде BORLAND C++ BUILDER. Средства интегрированной среды разработки. Характеристика визуальных компонентов..doc

 

ТЕМА  Работа в среде BORLAND C++ BUILDER. Средства интегрированной среды разработки. Характеристика визуальных компонентов.

ТИП: комбинированное занятие.

ЦЕЛИ :

Учебная :

·        изучить основные компоненты интегральное среда разработки (ИСР) C + + Builder..

·        научиться работать в среде разработки C++ Builder

Развивая :

·        • развивать логическое мышление , внимание , память ;

·        • развивать кругозор .

Воспитательная :

·        • развивать познавательный интерес к предмету.

·       Структура занятия

·       1 . Организационный момент ( 3 мин )

·       2 . Сообщения темы , цели занятия ( 5 мин )

·       3 . Актуализация знаний ( 10 мин )

·       4 . Выдача теоретического материала ( 20 мин )

·       5 . Проверка полученных знаний на практике ( 35 мин )

·       6 . Подведение итогов , выставление оценок ( 5 мин )

·       7 . Выдача домашнего задания ( 2 мин )

Литература.

1.     Шилдт Г. С++: базовый курс, 3-е издание.: Пер. с англ.-М. : Издательский дом "Вильямс", 2010

2.     Архангельский А. Я. "Програмирование в C++ Builder". - М.: "Издательство Бином", 2003

3.     Деннис Ритчи "Язык программирования C. 2-е издание, переработанное и дополненное" Пер. с англ.-М. : Издательский дом "Вильямс", 2009

4.     Керниган Б. "Язык программирования Си"-Питер. Невский Диалект, 2009

5.     Вильямс А. Системное программирование в Windows 2000 для профессионалов - СПб: Питер, 2003. - 624 с.: ил.

6.     Юркин А. Задачник по программированию. — СПб.: Питер, 2002. — 192 с.

Вопрос актуализации знаний:

1.     Основные компонента программы?

2.     Опешите этапы разработки программного продукта.

3.     Опишите знакомые среды разработки их преимущества и недостатки

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

1.     Опишите основные компоненты среда разработки C++ Builder.

2.     Что такое свойство компонента

3.     Что такое событие

4.     Опишите менеджер проектов

5.     Опишите этапы создания проектов в среда разработки C++ Builder

 

План.

  1. Введение
  2. Среда разработки C++ Builder
  3. Компоненты C++ Builder
    1. Свойства компонентов
    2. События
    3. Методы
  4. Менеджер проектов
  5. Создание приложений в С++ Builder
  6. Пример: создание простейшего приложения

Введение

Borland C++ Builder - выпущенное недавно компанией Borland средство быстрой разработки приложений, позволяющее создавать приложения на языке C++, используя при этом среду разработки и библиотеку компонентов Delphi. В настоящей статье рассматривается среда разработки C++ Builder и основные приемы, применяемые при проектировании пользовательского интерфейса.

Среда разработки C++ Builder

C++ Builder представляет собой SDI-приложение, главное окно которого содержит настраиваемую инструментальную панель (слева) и палитру компонентов (справа). Помимо этого, по умолчанию при запуске C++ Builder появляются окно инспектора объектов (слева) и форма нового приложения (справа). Под окном формы приложения находится окно редактора кода.

cb200000.gif

Рис.1. Среда разработки C++ Builder

Формы являются основой приложений C++ Builder. Создание пользовательского интерфейса приложения заключается в добавлении в окно формы элементов объектов C++ Builder, называемых компонентами. Компоненты C++ Builder располагаются на палитре компонентов, выполненной в виде многостраничного блокнота. Важная особенность C++ Builder состоит в том, что он позволяет создавать собственные компоненты и настраивать палитру компонентов, а также создавать различные версии палитры компонентов для разных проектов.

Компоненты C++ Builder

Компоненты разделяются на видимые (визуальные) и невидимые (невизуальные). Визуальные компоненты появляются во время выполнения точно так же, как и во время проектирования. Примерами являются кнопки и редактируемые поля. Невизуальные компоненты появляются во время проектирования как пиктограммы на форме. Они никогда не видны во время выполнения, но обладают определенной функциональностью (например, обеспечивают доступ к данным, вызывают стандартные диалоги Windows 95 и др.)

cb200001.gif

Рис. 2. Пример использования видимых и невидимых компонентов

Для добавления компонента в форму можно выбрать мышью нужный компонент в палитре и щелкнуть левой клавишей мыши в нужном месте проектируемой формы. Компонент появится на форме, и далее его можно перемещать, менять размеры и другие характеристики.

Каждый компонент C++ Builder имеет три разновидности характеристик: свойства, события и методы.

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

cb200002.gif

Рис.3. Инспектор объектов

Свойства компонентов

Свойства являются атрибутами компонента, определяющими его внешний вид и поведение. Многие свойства компонента в колонке свойств имеют значение, устанав иваемое по умолчанию (например, высота кнопок). Свойства компонента отображаются а странице свойств (Properties). Инспектор объектов отображает опубликованные (published) свойства компонентов. Помимо published-свойств, компоненты могут и чаще всего имеют общие (public), опубликованные свойства, которые доступны только во время выполнения приложения. Инспектор объектов используется для установки свойств во время проектирования. Список свойств располагается на странице свойств инспектора объектов. Можно определить свойства во время проектирования или написать код для видоизменения свойств компонента во время выполнения приложения.

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

События

Страница событий (Events) инспектора объектов показывает список событий, распознаваемых компонентом (программирование для операционных систем с графическим пользовательским интерфейсом, в частности, для Windows 95 или Windows NT предполагает описание реакции приложения на те или иные события, а сама операционная система занимается постоянным опросом компьютера с целью выявления наступления какого-либо события). Каждый компонент имеет свой собственный набор обработчиков событий. В C++ Builder следует писать функции, называемые обработчиками событий, и связывать события с этими функциями. Создавая обработчик того или и ого события, вы поручаете программе выполнить написанную функцию, если это событие произойдет.

Для того, чтобы добавить обработчик событий, нужно выбрать на форме с помощью мыши компонент, которому необходим обработчик событий, затем открыть страницу событий инспектора объектов и дважды щелкнуть левой клавишей мыши на колонке з ачений рядом с событием, чтобы заставить C++ Builder сгенерировать прототип обработчика событий и показать его в редакторе кода. При этом автоматически генерируется текст пустой функции, и редактор открывается в том месте, где следует вводить код. Курсор позиционируется внутри операторных скобок { ... }. Далее нужно ввести код, который должен выполняться при наступлении события. Обработчик событий может иметь параметры, которые указываются после имени функции в круглых скобках.

cb200003.gif

Рис.4. Прототип обработчика событий.

Методы

Метод является функцией, которая связана с компонентом, и которая объявляется как часть объекта. Создавая обработчики событий, можно вызывать методы, используя следующую нотацию: ->, например:

            Edit1->Show(); 

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

Менеджер проектов

Файлы, образующие приложение - формы и модули - собраны в проект. Менеджер проектов показывает списки файлов и модулей приложения и позволяет осуществ ять навигацию между ними. Можно вызвать менеджер проектов , выбрав пункт меню View/Project Manager. По умолчанию вновь созданный проект получает имя Project1.cpp.

cb200004.gif

Рис.5. Менеджер проектов

По умолчанию проект первоначально содержит файлы для одной формы и исходного кода одного модуля. Однако большинство проектов содержат несколько форм и модулей. Чтобы добавить модуль или форму к проекту, нужно щелкнуть правой кнопкой мыши и выбрать пункт New Form из контекстного меню. Можно также добавлять существующие формы и модули к проекту, используя кнопку Add контекстного меню менеджера проектов и выбирая модуль или форму, которую нужно добавить. Формы и модули можно удалить в любой момент в течение разработки проекта. Однако, из-за того, что форма связана всегда с модулем, нельзя удалить одно без удаления другого, за исключением случая, когда модуль не имеет связи с формой. Удалить модуль из проекта можно, используя кнопку Remove менеджера проектов.

Если выбрать кнопку Options в менеджере проектов, откроется диалоговая панель опций проекта, в которой можно выбрать главную форму приложения, определить, какие формы будут создаваться динамически, каковы параметры компиляции модулей (в том числе созданных в Delphi 2.0, так как C++ Builder может включать их в проекты) и компоновки.

cb200005.gif

Рис. 6. Установка опций проекта

Важным элементом среды разработки C++ Builder является контекстное меню, появляющееся при нажатии на правую клавишу мыши и предлагающее быстрый доступ к наиболее часто используемым командам.

Разумеется, C++ Builder обладает встроенной системой контекстно-зависимой помощи, доступной для любого элемента интерфейса и являющейся обширным источником справочной информации о C++ Builder.

Создание приложений в С++ Builder

Первым шагом в разработке приложения C++ Builder является создание проекта. Файлы проекта содержат сгенерированный автоматически исходный текст, который становится частью приложения, когда оно скомпилировано и подготовлено к выполнению. Чтобы создать новый проект, нужно выбрать пункт меню File/New Application.

C++ Builder создает файл проекта с именем по умолчанию Project1.cpp, а также make-файл с именем по умолчанию Project1.mak. При внесении изменений в проект, таких, как добавление новой формы, C++ Builder обновляет файл проекта.

cb200006.gif

Рис.7 Файл проекта

Проект или приложение обычно имеют несколько форм. Добавление формы к проекту создает следующие дополнительные файлы:

  • Файл формы с расширением.DFM, содержащий информацию о ресурсах окон для конструирования формы
  • Файл модуля с расширением.CPP, содержащий код на C++.
  • Заголовочный файл с расширением .H, содержащий описание класса формы.

Когда вы добавляете новую форму, файл проекта автоматически обновляется.

Для того чтобы добавить одну или более форм к проекту , выберите пункт меню File/New Form. Появится пустая форма, которая будет добавлена к проекту. Можно воспользоваться пунктом меню File/New, выбрать страницу Forms и выбрать подходящий шаблон из репозитория объектов.

cb200007.gif

Рис.8 Шаблоны форм

Для того, чтобы просто откомпилировать текущий проект, из меню Compile нужно выбрать пункт меню Compile. Для того, чтобы откомпилировать проект и создать исполняемый файл для текущего проекта, из меню Run нужно выбрать пункт меню Run. Компоновка проекта является инкрементной (перекомпилируются только изменившиеся модули).

Если при выполнении приложения возникает ошибка времени выполнения, C++ Builder делает паузу в выполнении программы и показывает редактор кода с курсором, установленным на операторе, являющемся источником ошибки. Прежде чем делать необходимую коррекцию, следует перезапустить приложение, выбирая пункт меню Run из контекстного меню или из меню Run, закрыть приложение и лишь затем вносить изменения в проект. В этом случае уменьшится вероятность потери ресурсов Windows.

Пример: создание простейшего приложения

Теперь попробуем создать простейшее приложение, позволяющее вводить текст в редактируемое поле и добавлять этот текст к списку при нажатии мышью на кнопку. Выберем пункт меню File/New Application для создания проекта и сохраним его главную форму под именем samp1.cpp, а сам проект под именем samp.mak. Поместим на форму компоненты Button, Edit и ListBox со страницы Standard палитры компонент.

cb200008.gif

Рис. 9. Размещение компонентов на форме

После этого выберем на форме компонент Edit и удалим текущее значение свойства Text. Затем установим свойство Caption для Button1 равным "Добавить".

Чтобы добавить обработчик события OnClick для кнопки Добавить, нужно выбрать эту кнопку на форме, открыть страницу событий в инспекторе объектов и дважды щелкнуть мышью на колонке справа от события OnClick. В соответствующей строке ввода появится имя функции. C++ Builder сгенерирует прототип обработчика событий и покажет его в редакторе кода. После этого следует ввести следующий код в операторные скобки { ... } тела функции:

            void __fastcall TForm1::Button1Click(TObject *Sender) 
            {
            if (!(Edit1->Text == "")) 
                        {
                        ListBox1->Items->Add(Edit1->Text); 
                        Edit1->Text = "" ; 
                        }
            } 

Для компиляции приложения в меню Run выберем пункт Run. Теперь можно что-нибудь ввести в редактируемое поле, нажать мышью на кнопку Добавить и убедиться, что вводимые строки добавляются к списку.

cb200009.gif

Рис.10. Так выглядит готовое приложение.

Теперь модифицируем приложение, добавив кнопки Удалить и Выход. Для этого добавим еще две кнопки, изменим их свойство Caption и создадим обработчики событий, связанных с нажатием на эти кнопки:

cb200010.gif

Рис. 11. Модифицированное приложение

Для кнопки Удалить:

            void __fastcall TForm1::Button2Click(TObject *Sender) 
            { 
                        if (!(ListBox1->ItemIndex == -1)) 
                        ListBox1->Items->Delete(ListBox1->ItemIndex);
            }

Для кнопки Выход:

            Close();

Сохраним и скомпилируем приложение, а затем протестируем его.

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

1.     Для чего предназначены типы данных?

2.     Назовите классификацию типов данных?

3.     Какую размерность имеют целочисленные типы?

4.     Какую размерность имеют вещественные  типы?

Литература.

7.                             Шилдт Г. С++: базовый курс, 3-е издание.: Пер. с англ.-М. : Издательский дом "Вильямс", 2010

8.                             Архангельский А. Я. "Програмирование в C++ Builder". - М.: "Издательство Бином", 2003

9.                             Деннис Ритчи "Язык программирования C. 2-е издание, переработанное и дополненное" Пер. с англ.-М. : Издательский дом "Вильямс", 2009

10.                         Керниган Б. "Язык программирования Си"-Питер. Невский Диалект, 2009

11.                         Вильямс А. Системное программирование в Windows 2000 для профессионалов - СПб: Питер, 2003. - 624 с.: ил.

12.                         Юркин А. Задачник по программированию. — СПб.: Питер, 2002. — 192 с.

 

Просмотрено: 0%
Просмотрено: 0%
Скачать материал
Скачать материал "Лекции по дисциплине "ОСНОВЫ АЛГОРИТМИЗАЦИИ И ПРОГРАММИРОВАНИЯ ""

Получите профессию

Технолог-калькулятор общественного питания

за 6 месяцев

Пройти курс

Рабочие листы
к вашим урокам

Скачать

Выбранный для просмотра документ Лекция 12 Составление и отладка программ с построением изображений. Анимация.doc

ТЕМА Работа с графикой и рисунками средствами Borland C++ Builder.

ТИП: комбинированное занятие.

ЦЕЛИ :

Учебная :

·        изучить основные графические функции.

·        научиться использовать графические функции при создании программ

Развивая :

·        • развивать логическое мышление , внимание , память ;

·        • развивать кругозор .

Воспитательная :

·        • развивать познавательный интерес к предмету.

·       Структура занятия

·       1 . Организационный момент ( 3 мин )

·       2 . Сообщения темы , цели занятия ( 5 мин )

·       3 . Актуализация знаний ( 10 мин )

·       4 . Выдача теоретического материала ( 20 мин )

·       5 . Проверка полученных знаний на практике ( 35 мин )

·       6 . Подведение итогов , выставление оценок ( 5 мин )

·       7 . Выдача домашнего задания ( 2 мин )

Литература.

1.     Шилдт Г. С++: базовый курс, 3-е издание.: Пер. с англ.-М. : Издательский дом "Вильямс", 2010

2.     Архангельский А. Я. "Програмирование в C++ Builder". - М.: "Издательство Бином", 2003

3.     Деннис Ритчи "Язык программирования C. 2-е издание, переработанное и дополненное" Пер. с англ.-М. : Издательский дом "Вильямс", 2009

4.     Керниган Б. "Язык программирования Си"-Питер. Невский Диалект, 2009

5.     Вильямс А. Системное программирование в Windows 2000 для профессионалов - СПб: Питер, 2003. - 624 с.: ил.

6.     Юркин А. Задачник по программированию. — СПб.: Питер, 2002. — 192 с.

Вопрос актуализации знаний:

1.     Приведите примеры графических примитивов?

2.     Что такое графические адаптеры?

3.     Какие графические режимы вы знаете?

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

  1. Чем определяются графические возможности адаптера?
  2. Дайте краткую характеристику наиболее распространенных адаптеров.
  3. Какая процедура используется для инициализации графического режима работы адаптера?
  4. Как осуществляется обращение к процедуре инициализации графического режима работы адаптера.
  5. Какая процедура осуществляет прекращение работы адаптера в графическом режиме?
  6. Как задаются координаты на графическом экране?
  7. Какая процедура выводит пиксель заданным цветом по указанным координатам? Как выглядит заголовок этой процедуры?
  8. Какая процедура осуществляет вычерчивание линии с указанными координатами начала и конца? Как выглядит заголовок этой процедуры?
  9. Какая процедура вычерчивает прямоугольник? Как выглядит заголовок этой процедуры?
  10. Какая процедура вычерчивает окружность? Как выглядит заголовок этой процедуры?
  11. Какая процедура устанавливает текущий цвет для выводимых линий и символов? Как выглядит заголовок этой процедуры?
  12. Какая процедура устанавливает цвет фона? Как выглядит заголовок этой процедуры?
  13. Какая процедура заполняет произвольную замкнутую фигуру, используя текущий стиль заполнения (узор и цвет)? Как выглядит заголовок этой процедуры?
  14. Какая процедура закрашивает прямоугольник текущим образцом узора и текущим цветом? Как выглядит заголовок этой процедуры?
  15. Какая процедура обводит линией и заполняет эллипс? Как выглядит заголовок этой процедуры?

 

План.

1.     Основные понятия

2.     Классы TBitmap, TIcon, TMetafile

2.1. Загрузка и сохранение графики

2.2. Загрузка и отрисовка графики

2.3. Модификация графики

2.4. Установка прозрачности

2.5. Захват изображений с экрана монитора

2.6. Использование буфера обмена для работы с графикой

2.7. Экономия ресурсов

2.8. Другие методы и свойства TBitmap, TIcon, TMetafile

3.     Класс TImage и визуальный компонент TImage

3.1. Загрузка и сохранение графики

3.2. Загрузка и отрисовка графики

3.3. Модификация графики

3.4. Установка прозрачности

3.5. Захват изображений с экрана монитора

3.6. Использование буфера обмена для работы с графикой

3.7. Экономия ресурсов

Основные понятия

В двух следующих параграфах будут рассмотрены еще два рода объектов, которые имеют отношение к выводу изображений (), а именно, графика и рисунок и классы и компоненты их инкапсулирующие.

·         Графика. Это растровое изображение некоторого файла или ресурса (битового образа, пиктограммы или метафайла). C++Builder определяет производные от базового класса TGraphic объектные классы TBitmap, Ticon и TMetafile, предназначенные для работы с графикой.
   Класс TBitmap, определен в Borland C++ Builder как Graphic::TBitmap, имеет свойства и методы, позволяющие создавать графические изображенеия, управлять их атрибутами, читать в память и сохранять как файлы DIB на диске. Graphic::TBitmap поддерживает как растровые графические изображения в виде массива пикселей, так и изображения в формате .bmp. Основное свойство класса - Canvas. Класс TGraphic предоставляет TBitmap минимальный стандартный интерфейс для работой с графикой.
   Классы TIcon и TMetafile также являются производными от базового класса TGraphic и имеют свойства и методы для работы с графикой, но в отличии от TBitmap не имеют свойства Canvas, что объясняется спецификой построения и использования изображений в формате *.ico и *.wmf (*.emf).

·         Рисунок представляет собой контейнер для графики, т.е. он может содержать любые классы графических объектов. Контейнерный класс TPicture может содержать битовый образ, пиктограмму, метафайл или некоторый другой графический тип, определенный пользователем, а приложение может стандартизовано обращаться ко всем объектам контейнера посредством объекта "рисунок". Класс TPicture инкапсулирован в класс TImage и визуальный компонент TImage, как их основной компонент и имеет возможность работы с иконоками, bmp-файлами и метафайлами. При некоторых дополнениях возможна работа с файлами других форматов (*.jpeg, *.jpg, *.gif).

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

Классы TBitmap, TIcon и TMetafile

В данном параграфе рассматривается использование не инкапсулированных в другие классы и компоненты Borland C++ Builder классов TBitmap, TIcon и TMetafile.

Загрузка и сохранение графики

Первый пример показывает создание объектов соответствующих классов, загрузку в них файлов и сохранение файлов:

//Создаем объекты
Graphics::TBitmap*   gBitmap = new Graphics::TBitmap;
Graphics::TIcon*     gIcon   = new Graphics::TIcon;
Graphics::TMetafile* gMFile  = new Graphics::TMetafile;
//Загружаем в них файлы
gBitmap->LoadFromFile("1.bmp");
gIcon->LoadFromFile("1.ico");
//Свойство показывает, что файл .emf win32
gMFile->Enhanced=true; 
gMFile->LoadFromFile("1.emf");
//Сохранение изображений в файлы
gBitmap->SaveToFile("1.bmp");
gIcon->SaveToFile("2.ico");
gMFile->SaveToFile("2.emf");
//Утверждается, что Borland C++ Builder
//собироет мусор сам, но не помешает
delete gBitmap;
delete gIcon;
delete gMFile;

Загрузка и отрисовка графики

Следущий код использует класс TBitmap для загрузки изображения из файла и его отрисовки, а также для задания растрового изображения кисти. Из рисунка, показывающего результаты работы программы, видно, что вновь для кисти используется не весь битовый образ, а только первые его 8*8 пикселей.

//Создаем объект TBitmap
Graphics::TBitmap*  gBitmap = new Graphics::TBitmap;
//Загружаем в него изображение
gBitmap->LoadFromFile("1.bmp");
//Рисуем на канве загруженное изобоажение
Canvas->Draw(10,10,gBitmap);
//Берем загруженное изобоажение в качестве кисти
//из которого используются только 8*8 пикселей
Canvas->Brush->Bitmap = gBitmap;
//Рисуем элипс
Canvas->Ellipse(85,10,160,85);

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

graphics_3.jpg

Рис 1. Использование класса TBitmap

Полностью аналогичен код и для графики в форматах .ico и .emf:

Graphics::TIcon*     gIcon  = new Graphics::TIcon;
Graphics::TMetafile* gMFile = new Graphics::TMetafile;
gIcon->LoadFromFile("1.ico");
gMFile->Enhanced=true;
gMFile->LoadFromFile("1.emf");
Canvas->Draw(10,10,gIcon);
Canvas->Draw(50,50,gMFile);
delete gIcon;
delete gMFile;

Для отрисовки графики можно использовать функцию StretchDraw(), которая, в отличие от функция Draw() не только рисует, но и масштабирует изображение. Однако, иконки не масштабируются - им только выделяется указанный в функции кусок канвы

TRect tRect(10,10,50,50);
Canvas->StretchDraw(tRect,gBitmap);
TRect tRect1(100,100,150,150);
Canvas->StretchDraw(tRect1,gIcon);
TRect tRect2(250,250,350,350);
Canvas->StretchDraw(tRect2,gMFile);

Метод CopyRect() также предназначен для отрисовки графики и переносит указанную область изображения или его часть в канве источника изображения в указанную область изображения данного объекта TCanvas. Копирование производится в режиме, установленном свойством CopyMode канвы, разноообразие которых можно посмотреть в Help Borland C++ Builder.

//Создаем объект TBitmap
Graphics::TBitmap*  gBitmap = new Graphics::TBitmap;
//Загружаем в него изображение
gBitmap->LoadFromFile("1.bmp");
//Определяем размеры областей копирования
TRect tRectFrom(0,0,25,25);
TRect tRectTo(10,10,35,35);
//CopyMode cmSrcCopy - прямое копирование
Canvas->CopyMode=cmSrcCopy;
//Копируем часть изображения
Canvas->CopyRect(tRectTo,gBitmap->Canvas,tRectFrom);

Модификация графики

Следущий пример показывает как можно создать объект TBitmap, выполнить на нем рисунок и перенести на канву приложения. К сожалению это нельзя сделать не для иконок, не для метафайлов, у которых нет сваойства Canvas.

Graphics::TBitmap*  gBitmap = new Graphics::TBitmap;
gBitmap->Width  = 150;
gBitmap->Height = 150;
gBitmap->Canvas->Ellipse(0,0,150,150);
Canvas->Draw(10,10,gBitmap);
delete  gBitmap;

Нижепреведенный код объединяет два примера, а именно на графическом изображении, полученном из файла выполняется некоторая отрисовка и новое изображение переносится на канву приложения. Результат - прямоугольник с закругленными краями желтого цвета заменяется на круг.

//Создаем объект TBitmap
Graphics::TBitmap*  gBitmap = new Graphics::TBitmap;
//Загружаем в него изображение
gBitmap->LoadFromFile("1.bmp");
//Задаем параметры кисти
gBitmap->Canvas->Brush->Color=clYellow;
//Рисуем на изображении файла круг
gBitmap->Canvas->Ellipse(0,0,gBitmap->Width,gBitmap->Height);
//Рисуем на канве загруженное изобоажение
Canvas->Draw(10,10,gBitmap);
delete  gBitmap;

Установка прозрачности

Bitmap может иметь один цвет, как прозрачный, тоесть цвет, который при выводе заменяется на цвет фона канвы отображения, не зависимо от смены ее цвета. Сделать это можно двумя способами. При первом способе определяется как "прозрачный" цвет левого верхнего пиксела Bitmap. При втором способе определяется прозрачным какой либо конкретный цвет. Установка того или иного способа определения прозрачных пикселов задается свойством TransparentMode (возможные значения для него - tmAuto и tmFixed соответственно). И в том, и в другом случае надо установить свойство Transparent для Bitmap в true.

//Создаем объект TBitmap
Graphics::TBitmap*  gBitmap = new Graphics::TBitmap;
//Установка свойства прозрачности
gBitmap->Transparent=true;
//Установка цвета левого верхнего
//пиксела в качестве прозрачного
gBitmap->TransparentMode=tmAuto;
gBitmap->LoadFromFile("1.bmp");
//Рисуем на канве загруженное изобоажение
Canvas->Draw(10,10,gBitmap);
//Установка конкретного цвета в качестве прозрачного
gBitmap->TransparentMode=tmFixed;
gBitmap->TransparentColor=clBlue;
Canvas->Draw(100,10,gBitmap);
delete  gBitmap;

Захват изображений с экрана монитора

В примере, описанном ниже, показано использование классов TCanvas и TBitmap для получения изображения с экрана монитора и сохранения его в файле. функция vPurloin() в зависимости от параметра, переданного ей, получает снимок экрана, окна приложения или клиентской части окна приложения (окна без заголовка) и сохраняет их в файл на диске. В принципе, этот пример использует и функции GDI для получение контекстов устройств и, в частности, экрана монитора, но основа, всеже, использование класса TBitmap.

Код функции:

void __fastcall
TForm1::vPurloin(int viI)
{
 //Создаем канву, которую будем использовать
 //для контекста рабочего стола
 TCanvas* tCanvas = new TCanvas;
 //Объект TBitmap также имеет канву
 Graphics::TBitmap*  gBitmap = new Graphics::TBitmap;
 //Размеры областей откуда и куда
 TRect tRectFrom;
 TRect tRectTo;
 //Исходные точки
 tRectFrom.Left=0;
 tRectFrom.Top=0;
 tRectTo.Left=0;
 tRectTo.Top=0;
 switch(viI)
 {
  case  0:
   //Делаем снимок всего рабочего
   //стола Для этого:
   // Получаем его Handle
   tCanvas->Handle = CreateDC("DISPLAY",NULL,NULL,NULL);
   //Устанавливаем размеры TBitmap
   //cоответствующие размеру экрана
   gBitmap->Width = Screen->Width;
   gBitmap->Height = Screen->Height;
   //Соответственно размеры для
   //функции копирования
   tRectFrom.Right=Screen->Width;
   tRectFrom.Bottom=Screen->Height;
   tRectTo.Right=Screen->Width;
   tRectTo.Bottom=Screen->Height;
  break;
  case 1:
   //Делаем снимок только окна приложения
   tCanvas->Handle = GetDC(0);
   //Устанавливаем размеры TBitmap
   //cоответствующие размеру окна
   gBitmap->Width = Width;
   gBitmap->Height = Height;
   //Соответственно размеры для
   //функции копирования
   //BoundsRect - Идентифицирует размер
   //окна приложения на экране
   tRectFrom=BoundsRect;
   Caption=tRectFrom.Left;
   tRectTo.Right=Width;
   tRectTo.Bottom=Height;
  break;
  case 2:
   //Всего окна приложения без заголовка
   //(клиентской области окна
   tCanvas->Handle = GetDC(Handle);
   //Устанавливаем размеры TBitmap cоответствующие
   //размеру клиенской области окна
   gBitmap->Width = ClientWidth;
   gBitmap->Height = ClientHeight;
   //Соответственно размеры для
   //функции копирования
   tRectFrom.Right=ClientWidth;
   tRectFrom.Bottom=ClientHeight;
   tRectTo.Right=ClientWidth;
   tRectTo.Bottom=ClientHeight;
  break;
 }
 //Копируем озображение в TBitmap с одной канвы в другую
 gBitmap->Canvas->CopyRect(tRectTo,tCanvas,tRectFrom);
 //Сохраняем в формате DIB
 gBitmap->SaveToFile("1.bmp");
 //Освобождаем ресурсы, хотя это выполняет само приложение
 delete gBitmap;
 delete tCanvas;
}

Использование буфера обмена для работы с графикой

Использование метода Assign позволяет проводить обмен данными между совершенно разнородными компонентами, например, компонентом буфера обмена TClipboard и графическим объектом TBitmap. Отметим, что следущий пример может быть повторен для метафайлов и не подходит для иконок, так как буфер обмена не поддерживает формат .ico. О том, как все же можно поместить в буфер обмена иконку Записать изображение в буфер можно оператором:

Clipboard()->Assign(gBitmap);

Прочитать изображение из буфера изображение оператором:

gBitmap->Assign(Clipboard());

Следующий пример деманстрирует возможности этих операторов:

.......
//Обязательно включить эту директиву
#include <Clipbrd.hpp>
......
void __fastcall 
TForm1::Button1Click(TObject *Sender)
{
 //Создаем объект TBitmap
 Graphics::TBitmap*  gBitmap = new Graphics::TBitmap;
 //Загружаем изображение
 gBitmap->LoadFromFile("1.bmp");
 //Копируем в буфер обмена
 Clipboard()->Assign(gBitmap);
 delete  gBitmap;
}
void __fastcall
TForm1::Button2Click(TObject *Sender)
{
 //Создаем объект TBitmap
 Graphics::TBitmap*  gBitmap = new Graphics::TBitmap;
 //Загружаем в него изображение из буфера обмена
 gBitmap->Assign(Clipboard());
 //Рисуем на канве загруженное изобоажение
 Canvas->Draw(10,10,gBitmap);
 delete  gBitmap;
}

Другой, но мало привлекательный метод работы с буфером обмена - SaveToClipboardFormat(). Он создает копию изображения в формате Clipboard - формат, указатель на данные и палитру, возвращаются как параметры функции. Стандартно зарегистрированные форматы: CF_BITMAP для битовых карт и CF_METAFILEPICT для метафайлов. Формат для нового типа графического объекта предварительно должен быть зарегистрирован методом RegisterClipboardFormat().

После применения метода SaveToClipboardFormat() надо передать объекту Clipboard полученные значения параметров.

Пример использования метода SaveToClipboardFormat():

.......
//Обязательно включить эту директиву
#include <Clipbrd.hpp>
......
//В любом обработчике пишем код:
//Определяем параметры функции SaveToClipboardFormat()
THandle   tDataHandle;
HPALETTE  hPalette;
Word      wFormat;
//Создаем два объекта TBitmap, чтобы доказать
//себе, что изображение получено именно из буфера
//хотя можно было воспользоваться методом Clear()
Graphics::TBitmap *gBitmap    = new Graphics::TBitmap();
Graphics::TBitmap *gBitmapNew = new Graphics::TBitmap();
//Загружаем изображение
gBitmap->LoadFromFile("1.bmp");
//Направляем в буфер и получаем параметры изображения
gBitmap->SaveToClipboardFormat(wFormat,
                                 tDataHandle,hPalette);
//Регистрируем формат в буфере обмена
Clipboard()->SetAsHandle(wFormat,tDataHandle);
//Если формат в буфере, соответствует исходному
if(Clipboard()->HasFormat(wFormat))
{
 //Загружаем изображение из буфера
 gBitmapNew->LoadFromClipboardFormat(wFormat,
                                     tDataHandle,hPalette);
 //Проводим отрисовку
 Canvas->Draw(5,5,gBitmapNew);
}else
{
  //Сообщение об ошибке
}
delete gBitmap;
delete gBitmapNew;

Экономия ресурсов

В этом примере показано освобождение ресурсов изображения на различных уровнях (методы Dormant(), FreeImage(), ReleaseHandle()), кроме того в примере показано как преобразовать изображение в монохромное (свойство Monochrome):

//Создаем объект TBitmap
Graphics::TBitmap*  gBitmap = new Graphics::TBitmap;
//Загружаем изображение в TBitmap
gBitmap->LoadFromFile("1.bmp");
//Освобождение ресурсов GDI занятых TBitmap
gBitmap->Dormant();
//Освобождение памяти, но изображение не удаляется
//пока на него есть ссылка (Handle), хотя его память
//и может быть занята другими объектами приложения
gBitmap->FreeImage();
//Рисуем изображение из TBitmap
Canvas->Draw(10,10,gBitmap);
//Устанавливается монохромный режим для TBitmap
gBitmap->Monochrome = true;
//Можно нарисовать монохромный вариант
Canvas->Draw(150,10,gBitmap);
//Убрать ссылку на изображение - изображение теряется
gBitmap->ReleaseHandle();
//Больше изображение не отображается
Canvas->Draw(300,10,gBitmap);
delete  gBitmap;

Аналогично можно использовать для освобождения ресурсов для графики в формате .ico и .emf.

Другие методы и свойства TBitmap, TIcon, TMetafile

Из интересных свойств отметим:

·         gBitmap->Handle, gBitmap->Palette - дескрипторы битовой карты и ее палитры.

·         HandleAllocated() - проверяет наличие дескриптора компонента у данного элемента. Если дескриптор имеется, то возвращается true. В отличии от проверки свойства Handle, этот метод не приводит к созданию дескриптора при его отсутствии.

·         ReleaseHandle() и ReleasePalette() - возвращают (обнуляет) дескриптор изображения и палитры соответственно. Следует отметить, что один объект может иметь несколько дескрипторов. При любом внешнем обращении к дескриптору битовой карты и попытке рисовать на ее канве объект получает собственную копию содержимого дескриптора (тоесть совместного использования дескрипторов нет).

·         ReleaseMaskHandle() - освобождает дескриптор маски точечного рисунка. Действие аналогично ReleasePalette.

·         Mask() - конвертирует текущее растровое изображение в одноцветную маску, заменяя TransparentColor белым цветом, остальные черным. Используется когда надо превратить битовую карту в маску для других битовых карт. Для преобразования могут использоваться свойства MaskHandle, и метод ReleaseMaskHandle().

·         Свойство HandleType - может принимать значения bmDIB или bmDDB и позволяет проверить тип изображение (DDB или DIB).

·         Свойство PixelFormat - позволяет определить и изменить формат изображения. Возможные значения - pfDevice, pf1bit, pf4bit, pf8bit, pf15bit, pf16bit, pf24bit, pf32bit, pfCustom. Режим pfDevice соответствует битовой карте DDB. Глубина цвета в 1, 4 и 8 бит на пиксел предусматривает наличие у изображения палитры. Другие режимы хранят значения яркостей точек в каждом из трех основных цветов - красном (R), зеленом (G) и синем (В). Разрядность 15 бит соответствует распределению бит 5-5-5 (RGB555), 16 бит - RGB 565, 24 бит - RGB888. Режим 32 бит похож на 24-битный, но в нем дополнительно добавлен четвертый канал (альфа-канал), содержащий дополнительную информацию о прозрачности каждой точки. Режим pfCustom предназначен для реализации программистом собственных графических конструкций (использовать его целесообразно только в собственных потомках TBitmap).

Простейший пример предбразования:

 Graphics::TBitmap *gBitmap = new Graphics::TBitmap();
 gBitmap->LoadFromFile("1.bmp");
 //Преобразуем из того, что имели в формат TrueColor
 gBitmap->PixelFormat=pf24bit;
 Canvas->Draw(10,10,gBitmap);

·         IgnorePalette - требование игнолировать палитру при значении true, увеличивает скорость работы с изображением, но ведет к потери качества для изображений особенно 16 и 256 цветов.

·         ScanLine[] - обеспечивает индексированный доступ к строкам пикселов растрового изображения. Метод используется только с форматами растрового изображения DIB.

·                Byte *ptr,
·                //Если "y" - нометр строки, то получить
·                //указатель на строку байт линии
·                ptr = (Byte *)gBitmap->ScanLine[y];

Внутри строки данные упорядочены в соответствии с форматом (pixelFormat). Для формата pf1bit каждый бит в строке соответствует одному пикселу, для форматов до pf24bit пикселу соответствуют два байта, pf24bit - три байта (по байту на канал), pf32bit - четыре байта.

Класс TImage и работа с изображениями

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

Большинство свойств компонента TImage такиеже как и у многих других компонент (положение изобрыжения на форме, его размеры, помощь, отображение подсказок и т.п.). Среди "не стандартных" свойств, отметим:

·         Picture. Контейнер графики. Окно загрузки файлов изображений открывается кнопкой в графе свойства Picture компонента TImage. Кроме того это свойство имеет методы LoadFromFile(), SaveToFile().

·         AutoSize. Чтобы контейнер изменил свои размеры так, чтобы вместить изображение целиком, устанавливается значение true свойства AutoSize.

·         Stretch. Чтобы исходное изображение растянулось на весь контейнер, задается значение true свойства Stretch.

·         Center - если AutoSize=false, то изображение помещается в центре компонента.

·         IncrementalDisplay - если true, то при загрузке больших файлов они будут показываться по частям по мере загрузки.

·         Transparent - считает цвет одного из угловых пикселей цветом прозрачности (левый нижний).

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

//Визуальный компонент
Image1->Canvas...
//Класс
TImage *tImage;
tImage=new TImage(this);
tImage->Canvas

Рассмотрение вопросов параграфа темы будем вести на примерах, в которых последовательно показывается использование основных свойств и методов компонента и класса TImage. Работа с ресурсами выделена в отдельный раздел и здесь опущена.

Кроме того, так как эти классы инкапсулируют в свойстве TPicture классы TBitmap, TIcon и TMetafile, то все, что относится непосредственно к работе с этими классами, более подробно можно посмотреть в предыдущем параграфе. Здесь же основное внимание уделено технологии работе с классами.

Загрузка и сохранение графики

Методы LoadFromFile() и SaveToFile() объектного свойства Picture служат для динамической загрузки и сохранения файлов изображений с помощью инструкций типа, которые могут быть использованы двояко:

Image1->Picture->LoadFromFile("1.bmp");
Image1->Picture->SaveToFile("2.bmp");
.....
Image1->Picture->LoadFromFile("1.ico");
Image1->Picture->SaveToFile("2.ico");
.....
//Свойство Enhanced показывает, что файл .emf win32
Image1->Picture->Metafile->Enhanced=true;
Image1->Picture->LoadFromFile("1.emf");
Image1->Picture->SaveToFile("2.emf");
.....
Image1->Picture->Bitmap->LoadFromFile("1.bmp");
Image1->Picture->Bitmap->SaveToFile("2.bmp");
.....
Image1->Picture->Icon->LoadFromFile("1.ico");
Image1->Picture->Icon->SaveToFile("2.ico");
.....
//Свойство показывает, что файл .emf win32
Image1->Picture->Metafile->Enhanced=true;
Image1->Picture->Metafile->LoadFromFile("1.emf");
Image1->Picture->Metafile->SaveToFile("2.emf");
.....
//Аналогично для класса
TImage *tImage;
tImage=new TImage(this);
tImage->Picture->LoadFromFile("1.bmp");
tImage->Picture->SaveToFile("2.bmp");
.......
delete tImage;

Загрузка и отрисовка графики

Отрисовка графики при использовании визуального компонента предельно проста - изображение отображается сразу при загрузке в компонент. При этом можно управлять многими параметрами изображений, например:

Image1->Left=50;
Image1->Top=50;
Image1->Width=200;
Image1->Height=200;
//Устанавливаем прозрачность, по умолчанию tmAuto
Image1->Transparent=true;
Image1->Picture->LoadFromFile("1.bmp"); 

Для отображения графики, загруженной в созданный класс TImage, можно как и ранее воспользоваться функциями Draw() и StretchDraw():

TImage *tImage;
tImage=new TImage(this);
tImage->Picture->LoadFromFile("1.bmp");
tImage->Transparent=true;
Canvas->Draw(100,0,tImage->Picture->Bitmap);
            delete tImage;

Отметим, что масштабирования Bitmap в классе не предусмотрено и это возможно только при отрисовки, например функцией StretchDraw():

TRect tRect(0,0,500,250);
Canvas->StretchDraw(tRect,tImage->Picture->Bitmap);

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

TImage *tImage;
tImage=new TImage(this);
tImage->Picture->Metafile->Enhanced=true;
tImage->Picture->Metafile->LoadFromFile("1.emf");
tImage->Center=true;
tImage->Picture->Metafile->Width=250;
tImage->Picture->Metafile->Height=250;
tImage->Stretch=true;
Canvas->Draw(100,0,tImage->Picture->Metafile);
delete tImage;

Отметим, что класс поддерживает масштабирование для метафайлов.

И для визуальных компонентов:

Image1->Left=0;
Image1->Top=0;
Image1->Width=250;
Image1->Height=250;
Image1->Center=true;
Image1->Stretch=true;
Image1->Picture->Metafile->Enhanced=true;
Image1->Picture->Metafile->LoadFromFile("1.emf");

Обратим внимание на некоторое различие на задание размеров отображаемого рисунка. Такая конструкция не сработает для TImage:

Image1->Picture->Metafile->Width=250;
Image1->Picture->Metafile->Height=250;

И, как и в случае с объектным классом TIcon, не сработает никакой из способов задания размеров для иконки, в том числе и для визуального компонента. Иконка не изменит своих размеров в следующем коде:

//Это работает
Image1->Left=0;
Image1->Top=0;
//Эти операторы - нет
Image1->Width=250;
Image1->Height=250;
Image1->Center=true;
Image1->Stretch=true;
//Отображаем иконку
Image1->Picture->Icon->LoadFromFile("1.ico");

Аналогично и для класса TImage:

 
TImage *tImage;
tImage=new TImage(this);
//Четыре опера не работают
tImage->Picture->Icon->Width=250;
tImage->Picture->Icon->Height=250;
tImage->Center=true;
tImage->Stretch=true;
//Загружаем иконку
tImage->Picture->Icon->LoadFromFile("1.ico");
//Отображаем иконку
Canvas->Draw(0,0,tImage->Picture->Icon);
delete tImage;

Метод CopyRect() также предназначен для отрисовки изображений, переносит указанную область изображения или его часть в канве источника изображения в указанную область данного объекта TCanvas. Копирование производится в режиме, установленном свойством CopyMode канвы, разноообразие которых можно посмотреть в Help Borland C++ Builder.

Следующий код показывает возможность копирования части изображения:

 
//Загружаем  изображение
Image1->Picture->Bitmap->LoadFromFile("1.bmp");
//Определяем размеры областей копирования
TRect tRectFrom(0,0,25,25);
TRect tRectTo(10,10,35,35);
//CopyMode cmSrcCopy - прямое копирование
Canvas->CopyMode=cmSrcCopy;
//Копируем часть изображения
Canvas->CopyRect(tRectTo,Image1->Picture->Bitmap->Canvas,tRectFrom);

Этот метод позволяет и увеличить размер изображения иконки как показано в следующем примере:

//Загружаем  изображение иконки
Image1->Picture->Icon->LoadFromFile("1.ico");
//Рисуем ее на канве
Canvas->Draw(0,0,Image1->Picture->Icon);
//Определяем размеры областей копирования
TRect tRectFrom(0,0,32,32);
//Эта область в два раза больше
TRect tRectTo(50,50,114,114);
//CopyMode cmSrcCopy - прямое копирование
Canvas->CopyMode=cmSrcCopy;
//Копируем иконку в увеличенном виде
Canvas->CopyRect(tRectTo,Canvas,tRectFrom);

Модификация графики

Следущие примеры показывают возможность выполнить некоторый рисунок на уже загруженном изображении. К сожалению это нельзя сделать не для иконок, не для метафайлов, у которых нет сваойства Canvas.

Для визуального компонента:

Image1->AutoSize=true;
//Загружаем в него изображение
Image1->Picture->Bitmap->LoadFromFile("1.bmp");
//Задаем параметры кисти
Image1->Picture->Bitmap->Canvas->Brush->Color=clYellow;
//Рисуем на изображении круг
Image1->Picture->Bitmap->Canvas->Ellipse(0,0,
                  Image1->Picture->Bitmap->Width,
                   Image1->Picture->Bitmap->Height);

Аналогично для класса:

TImage *tImage;
tImage=new TImage(this);
tImage->Picture->Bitmap->LoadFromFile("1.bmp");
tImage->Picture->Bitmap->Canvas->Brush->Color=clYellow;
tImage->Picture->Bitmap->Canvas->Ellipse(0,0,
                  tImage->Picture->Bitmap->Width,
                  tImage->Picture->Bitmap->Height);
Canvas->Draw(0,0,tImage->Picture->Bitmap);
delete tImage;

Установка прозрачности

Все сказанное выше равным образом относится и для Timage, поэтому останавливаться на этом не будем. В примерах параграфа "Загрузка и отрисовка изображений" уже использовалось свойство Transparent для TImage. Отметим, что для иконок, если они созданы (например в Tools/Image Editor) как имеющие области прозрачности, установка свойства Transparent в false не поможет.

Пример установки прозрачности для класса TImage:

TImage *tImage;
tImage=new TImage(this);
tImage->Transparent=true;
//Установка цвета левого верхнего
//пиксела в качестве прозрачного
tImage->Picture->Bitmap->TransparentMode=tmAuto;
tImage->Picture->Bitmap->LoadFromFile("1.bmp");
Canvas->Draw(0,0,tImage->Picture->Bitmap);
//Или так
tImage->Picture->Bitmap->TransparentMode=tmFixed;
tImage->Picture->Bitmap->TransparentColor=clRed;
Canvas->Draw(100,0,tImage->Picture->Bitmap);
delete tImage;

Тоже для визуального компонента:

Image1->Transparent=true;
//Установка цвета левого верхнего
//пиксела в качестве прозрачного
Image1->Picture->Bitmap->TransparentMode=tmAuto;
Image1->Picture->Bitmap->LoadFromFile("1.bmp");
//Или сменить цвет прозрачности
Image1->Picture->Bitmap->TransparentMode=tmFixed;
Image1->Picture->Bitmap->TransparentColor=clRed;

Захват изображений с экрана монитора

Самый простой способ получить изображение экрана монитора это присвоить Handle канвы TImage Handle экрана или окна приложения:

Image1->Width=Screen->Width;
Image1->Height=Screen->Height;
Image1->Canvas->Handle=CreateDC("DISPLAY",NULL,NULL,NULL);
.........
Image1->Width=Width;
Image1->Height=Height;
Image1->Canvas->Handle=GetDC(Handle);

Недостаток этого способа в том, что снимки нельзя масштабировать. Поэтому при необходимости масштабирования можно применить подход описанный для TBitmap, что для TImage выглядит так:

//Создаем канву, которую будем использовать
//для контекста рабочего стола
TCanvas* tCanvas = new TCanvas;
//Размеры областей откуда и куда
TRect tRectFrom;
TRect tRectTo;
//Исходные точки
tRectFrom.Left=0;
tRectFrom.Top=0;
tRectTo.Left=0;
tRectTo.Top=0;
//Делаем снимок всего рабочего
//стола Для этого получаем его Handle
tCanvas->Handle = CreateDC("DISPLAY",NULL,NULL,NULL);
//Устанавливаем размеры TBitmap cоответствующие размеру экрана
Image1->Picture->Bitmap->Width = Screen->Width;
Image1->Picture->Bitmap->Height = Screen->Height;
//Соответственно размеры для функции копирования
tRectFrom.Right=Screen->Width;
tRectFrom.Bottom=Screen->Height;
tRectTo.Right=Screen->Width;
tRectTo.Bottom=Screen->Height;
//Копируем озображение в TBitmap с одной канвы в другую
Image1->Picture->Bitmap->Canvas->CopyRect(tRectTo,tCanvas,tRectFrom);
//Изображение экрана можно сохранить в памяти
Image1->Picture->SaveToFile("a.bmp");
//Масштабируем изображение
Image1->Stretch=true;
delete tCanvas;

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

//Клиентская область окна
tCanvas->Handle = GetDC(Handle);
//Устанавливаем размеры TBitmap cоответствующие
//размеру клиенской области окна
Image1->Picture->Bitmap->Width = ClientWidth;
Image1->Picture->Bitmap->Height = ClientHeight;
//Соответственно размеры для функции копирования
tRectFrom.Right=ClientWidth;
tRectFrom.Bottom=ClientHeight;
tRectTo.Right=ClientWidth;
tRectTo.Bottom=ClientHeight;

Использование буфера обмена для работы с графикой

Использование буфера обмена для работы с изображением для TImage также ничем не отличается от описанных выше способов для TBitmap, где отмечены и особенности использование методов для различных графических объектов. Поэтому в данном параграфе приведены лишь примеры.

Записать изображение в буфер и прочитать его можно операторами:

Image1->Picture->Bitmap->LoadFromFile("1.bmp");
Clipboard()->Assign(Image1->Picture->Bitmap);
Image1->Picture->Bitmap->Assign(Clipboard());

И пример, использования функции SaveToClipboardFormat(), описание которой приводилось ранее:

//Определяем параметры функции SaveToClipboardFormat()
THandle   tDataHandle;
HPALETTE  hPalette;
Word      wFormat;
//Загружаем изображение в класс TImage
TImage *tImage;
tImage=new TImage(this);
tImage->Picture->Bitmap->LoadFromFile("1.bmp");
//Направляем в буфер и получаем параметры изображения
tImage->Picture->Bitmap->SaveToClipboardFormat(wFormat,
                                               tDataHandle,hPalette);
//Регистрируем формат в буфере обмена
Clipboard()->SetAsHandle(wFormat,tDataHandle);
//Удаляем объект TImage
delete tImage;
//Если формат в буфере, соответствует исходному
if(Clipboard()->HasFormat(wFormat))
{
 //Загружаем изображение из буфера
 Image1->Picture->Bitmap->LoadFromClipboardFormat(wFormat,
                                    tDataHandle,hPalette);
 //Можно провести отрисовку
 Canvas->Draw(5,5,Image1->Picture->Bitmap);
}else
{
 //Сообщение об ошибке
}

Экономия ресурсов

Этот пример полностью аналогичен, примеру для класса TBitmap:

 
//Загружаем изображение
Image1->Picture->Bitmap->LoadFromFile("1.bmp");
//Освобождение ресурсов GDI
Image1->Picture->Bitmap->Dormant();
//Освобождение памяти, но изображение не удаляется
//пока на него есть ссылка (Handle), хотя его память
//и может быть занята другими объектами приложения
Image1->Picture->Bitmap->FreeImage();
//Рисуем изображение из TBitmap
Canvas->Draw(10,10,Image1->Picture->Bitmap);
//Устанавливается монохромный режим для TBitmap
Image1->Picture->Bitmap->Monochrome = true;
//Можно нарисовать монохромный вариант
Canvas->Draw(150,10,Image1->Picture->Bitmap);
//Убрать ссылку на изображение - изображение теряется
Image1->Picture->Bitmap->ReleaseHandle();
//Больше изображение не отображается
Canvas->Draw(300,10,Image1->Picture->Bitmap);

 

Просмотрено: 0%
Просмотрено: 0%
Скачать материал
Скачать материал "Лекции по дисциплине "ОСНОВЫ АЛГОРИТМИЗАЦИИ И ПРОГРАММИРОВАНИЯ ""

Получите профессию

Экскурсовод (гид)

за 6 месяцев

Пройти курс

Рабочие листы
к вашим урокам

Скачать

Выбранный для просмотра документ Лекция 13 Создание многодокументных дополнений.doc

ТЕМА Проекти C++ Builder

ТИП: комбинированное занятие.

ЦЕЛИ :

Учебная :

·        изучить основные компоненты интегральное среда разработки (ИСР) C + + Builder..

·        научиться работать в среде разработки C++ Builder

Развивая :

·        • развивать логическое мышление , внимание , память ;

·        • развивать кругозор .

Воспитательная :

·        • развивать познавательный интерес к предмету.

·       Структура занятия

·       1 . Организационный момент ( 3 мин )

·       2 . Сообщения темы , цели занятия ( 5 мин )

·       3 . Актуализация знаний ( 10 мин )

·       4 . Выдача теоретического материала ( 20 мин )

·       5 . Проверка полученных знаний на практике ( 35 мин )

·       6 . Подведение итогов , выставление оценок ( 5 мин )

·       7 . Выдача домашнего задания ( 2 мин )

Литература.

1.     Шилдт Г. С++: базовый курс, 3-е издание.: Пер. с англ.-М. : Издательский дом "Вильямс", 2010

2.     Архангельский А. Я. "Програмирование в C++ Builder". - М.: "Издательство Бином", 2003

3.     Деннис Ритчи "Язык программирования C. 2-е издание, переработанное и дополненное" Пер. с англ.-М. : Издательский дом "Вильямс", 2009

4.     Керниган Б. "Язык программирования Си"-Питер. Невский Диалект, 2009

5.     Вильямс А. Системное программирование в Windows 2000 для профессионалов - СПб: Питер, 2003. - 624 с.: ил.

6.     Юркин А. Задачник по программированию. — СПб.: Питер, 2002. — 192 с.

Вопрос актуализации знаний:

1.     Основные компонента программы?

2.     Опешите этапы разработки программного продукта.

3.     Опишите знакомые среды разработки их преимущества и недостатки

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

1.     Опишите основные компоненты среда разработки C++ Builder.

2.     Что такое свойство компонента

3.     Что такое событие

4.     Опишите менеджер проектов

5.     Опишите этапы создания проектов в среда разработки C++ Builder

 

План.

Главным визуальным компонентом, используемым для проектирования пользовательского интерфейса программы, является форма. Форма соответствует окну создаваемого приложения и используется для размещения на нем прочих визуальных компонентов – кнопок, полей ввода, списков и т.п. Обычно пустая форма создается автоматически при создании нового приложения с помощью C++ Builder. Сложные программные продукты могут состоять из большого числа различных форм. Рассмотрим основные аспекты разработки многооконных приложений:

1.                 Создадим новый проект приложения командой File| New| Application из главного меню. Как уже было сказано, в приложение будет автоматически добавлена пустая форма. Ей соответствуют модуль программного кода (по умолчанию unit1.cpp), заголовочный файл (unit1.h) и файл описания формы C++ Builder (unit1.dfm).    

2.                 Для добавления новой формы в проект приложения необходимо вызвать команду File| New| Form главного меню или нажать соответствующую кнопку на панели инструментов. В этом случае проекте появится еще одна пустая форма, для описание которой также состоит из трех файлов, имена по умолчанию для которых, соотвтетственно, unit2.cpp, unit2.h и unit2.dfm.

3.                 Вызовом команды Project| View Source из главного меню можно открыть в редакторе кода основной файл проекта (по умолчанию он называется Project1.cpp). После выполнения описанных выше действий в нем автоматически генерируются следующие строки (см. функцию WinMain):

        Application->Initialize();

       Application->CreateForm(__classid(TForm1), &Form1);

 Application->CreateForm(__classid(TForm2), &Form2);

       Application->Run();

За оператором инициализации объекта приложения (первая строка) здесь располагается список операторов, отвечающих за инициализацию форм приложения. Для каждой формы приложения вызывается метод CreateForm («создать форму») объекта приложения Application.  В рассматриваемом случае приложение состоит из 2 форм. Форма, которая создается самой первой (в данном случае – это Form1), считается главной формой приложения. Главная форма автоматически отображается на экране при запуске приложения, в то время как остальные формы (которые иногда называют вторичными) будут созданы, но останутся невидимыми для пользователя до тех пор, пока не будут явно отображены на экране (рекомендуется убедиться в этом, запустив приложение). Закрытие главной формы означает завершение всей работы приложения. Закрытие остальных форм может привести к завершению работы приложения только, если об этом специально позаботится программист.

4.                 Главную форму приложения можно изменить, соответствующим образом отредактировав вышеописанный список инициализируемых форм приложения. Кроме того, это можно сделать из окна свойств проекта, который вызывается сочетанием клавиш Shift+Ctrl+F11 или командой Project| Options главного меню. На вкладке Forms появившегося окна можно обнаружить свойство Main form, которому можно назначить любую форму приложения. Укажем, например, для нашего приложения форму Form2 в качестве главной. Изменение и подтверждение указанного свойства приведет к автоматическому помещению оператора создания соответствующей формы на самый верх списка инициализации форм приложения (см. файл Project.cpp в редакторе кода). После запуска приложения мы увидим, что теперь стала видимой форма Form2, а ее закрытие завершает работу приложения.

5.                 Попробуем теперь вызвать из главной формы приложения (From2) вторичную форму Form1. Для этого поместим на форму Form2 кнопку, озаглавив ее “Form1”. В качестве реакции на  событие нажатия этой кнопки напишем следующее:

Form1->Show();

В данном случае предполагается отобразить форму Form1 на экране, за что отвечает метод Show() компонента формы. Попробуем откомпилировать и запустить приложение. Процесс компиляции проекта будет прерван с ошибкой “Undefined symbolForm1’”. Причина этого заключается в том, что описание класса формы Form1 находится в заголовочном файле unit1.h. Поэтому прежде чем обращаться к форме Form1 из модуля формы Form2, необходимо подключить к нему заголовочный файл unit1.h. Это можно сделать вручную, добавив в include-секцию модуля unit2.cpp соответствующую запись (includeunit1.h”), либо открыть модуль unit2.cpp в редакторе кода, а затем вызвать команду главного меню File| Include Unit Hdr и выбрать нужный файл из предлагаемого списка заголовочных файлов проекта. И в том, и в другом случае include-секция модуля главной формы будет содержать заголовочный файл формы Form1, поэтому повторная компиляция проекта будет успешной. Нажатие кнопки “Form1” в запущенном приложении приведет к отображению на экране формы с одноименным названием. После вызова формы Form1 пользователь может свободно переключаться между обеими формами. Форму Form1 можно закрывать и снова вызывать повторными нажатиями кнопки на главной форме. Из этого факта можно сделать вывод, что закрытие неглавной формы по умолчанию не приводит к уничтожению объекта, а всего лишь делает эту форму невидимой. Таким образом, по умолчанию объект формы Form1 существует все время работы приложения, до тех пор, пока не будет закрыта форма Form2.

6.                 Результат закрытия любой неглавной формы можно изменить. Завершим запущенное приложение, откроем форму Form1 (для переключения между формами проекта целесообразно использовать список форм, который вызывается сочетанием клавиш Shift+F12 или командой View| Forms из главного меню) и в качестве реакции на событие OnClose запишем следующее:

Action = caFree;

Если пользователь закрывает форму, то за действия объекта формы в этот момент отвечает параметр Action, который специально объявлен  в обработчике событий OnClose. Он относится к перечислимому типу TCloseAction и может принимать одно из следующих значений:

·                    caNone – при закрытии формы никакие действия не производятся, т.е. форма не закрывается.

·                    caHide – при закрытии формы ее объект не уничтожается, но форма становится невидимой для пользователя.

·                    caFree – при закрытии формы ее объект уничтожается, занимаемая им память высвобождается, так что больше этой формы в запущенном приложении не существует.

·                    caMinimize – закрытие формы означает ее минимизацию на экране. Форма остается видимой, объект не уничтожается.

По умолчанию параметр Aсtion принимает значение caHide. Попробуем еще раз запустить приложение со значением параметра Action, измененным на caFree. При первом нажатии кнопки “Form1” форма по-прежнему вызывается и отображается на экране. Однако при ее закрытии объект формы будет уничтожен, следовательно, после ее закрытия обращаться к ней больше нельзя. Поэтому повторное нажатие кнопки на главной форме приводит к возникновению ошибки некорректного доступа к памяти.

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

·                               Фиксированный размер;

·                               Фиксированное размещение относительно главного окна;

·                               Наличие кнопки OK и других стандартных кнопок («Отмена», «Да», «Нет» и т.п.).

·                               Работа приложения приостанавливается (т.е. все прочие окна приложения остаются недоступными) до завершения работы с диалоговым окном

В C++ Builder диалоговое окно является разновидностью обычной формы. Добавим в рассматриваемый проект еще одну форму Form3. С помощью инспектора объектов необходимо изменить свойство  BorderStyle у добавленной формы. Указанное свойство характеризует внешний вид и поведение границы формы. По умолчанию значение этого свойства установлено в bsSizeable, что означает, что пользователь может изменять размеры формы стандартным образом (например, потянув мышью за ее правый нижний угол). Для диалогового окна свойству BorderStyle следует присвоить значение bsDialog. В этом случае при запуске приложения форма будет иметь фиксированный размер, определенный при разработке приложения. Кроме того, как и полагается для диалоговых окон, кнопки максимизации и минимизации окна формы исчезнут из системного меню.

Способ размещения диалогового окна по отношению к главному окну программы следует указывать с использованием свойства формы Position. Для того, чтобы окно всегда размещалось в центре поверх главного окна, необходимо установить его значение в poMainFormCenter. Размеры формы Form3 лучше сделать несколько меньше, чем у формы Form2, чтобы при работе приложения они не сливались.

8.                  Поместим на форму Form2 еще одну кнопку с заголовком “Dialog”. В качестве реакции на нажатие кнопки запишем:

Form3->ShowModal();

В отличие от формы Form1 форма Form3 будет отображаться на экране в модальном режиме. Это значит, что после ее появления на экране все остальные формы приложения  будут оставаться недоступными до тех пор, пока форма не будет закрыта. Рекомендуется убедиться в этом, запустив рассматриваемое приложение. Перед компиляцией проекта необходимо добавить в include-секцию модуля формы Form2 заголовочный файл формы Form3 (unit3.h).

9.                 Из неглавных форм можно обращаться к объекту главной формы (или других неглавных форм) точно так же, как это было описано выше. Добавим, например, в include-секцию модуля формы Form1 заголовочный файл главной формы unit2.h. Теперь можно описать обработчик события отображения формы Form1 на экране следующим образом:

void __fastcall TForm1::FormShow(TObject *Sender)

{

 Form2->Button1->Enabled = false;

}

При появлении на экране формы Form1 будет выполнена вышеприведенная процедура, которая сделает кнопку “Form1” на главной форме недоступной для пользователя. Таким образом, повторное нажатие на эту кнопку станет невозможным, следовательно, ошибка некорректного доступа к памяти появляться не будет.

10.            В заключение отметим, что при создании многооконных приложений нередко бывает целесообразным использовать готовые шаблоны форм, которые хранятся в хранилище объектов Borland C++ Builder. Чтобы добавить в проект форму, основанную на каком-либо шаблоне, необходимо вызвать из главного меню команду File| New| Other. Появится окно хранилища объектов, в котором различные шаблоны форм предлагаются на вкладках Forms и Dialogs. Формы, созданные по шаблонам, в отличие от обычных форм, не являются пустыми и предлагают разработчику реализацию некоторого интерфейса и/или каких-либо функций. Программист C++ Builder имеет возможность добавлять в хранилище объектов и собственные шаблоны форм.

 

Мультидокументный интерфейс

 

         Все предыдущие замечания по поводу создания и работы с формами предполагают проектирование приложения с однодокументным интерфейсом.

         Однодокументный интерфейс (SDI-интерфейс, Single Document Interface) – это метод организации графического пользовательского интерфейса в виде набора самостоятельных окон, каждое из которых имеет собственный дескриптор операционной системы (то есть ОС рассматривает каждое из окон как самостоятельный объект). Все окна располагаются прямо на рабочем столе, при максимизации могут разворачиваться на весь рабочий стол, а при минимизации – сворачиваться на панель задач или в нижнюю часть рабочего стола.

         Другим способом организации графического пользовательского интерфейса является мультидокументный интерфейс (MDI-интерфейс, Multiple Document Interface). История его создания началась в конце 80-ых годов прошлого века, когда фирма IBM выпустила первую спецификацию соответствующего интерфейса. Его основные черты с тех пор практически не изменились:

·                   Приложение состоит из основного окна и ряда дочерних окон. Все дочерние окна находятся в границах родительского окна.

·                   Приложение и каждое дочернее окно допускает максимизацию и минимизацию. Максимизированные и минимизированные дочерние окна остаются в рамках основного окна.

·                   Основное окно имеет меню, расположенное в верхней части. Список всех дочерних окон содержится в выпадающем подменю, имеющем название Window (Окно).

·                   Приложение закрывается комбинацией Alt+F4, а дочернее окно – Ctrl+F4. Сочетание клавиш Ctrl+F6 используется для переключения между дочерними документами.

 

Среда разработки приложений Borland C++ Builder позволяет довольно просто разрабатывать приложения с мультидокументным интерфейсом. Чтобы создать MDI-приложение обычно требуется выполнение следующих шагов:

1.                 В только что созданном приложении установить значение свойства FormStyle равным fsMDIForm (по умолчанию его значение равно fsNormal). Тогда главная форма приложения станет основным окном многодокументного интерфейса.

2.                 Для каждой формы, которая проектируется как дочерняя, необходимо устанавливать значение свойства FormStyle равным fsMDIChild.

3.                 Особенностью дочерних окон приложения с MDI является невозможность сделать их невидимыми. Поэтому все дочерние окна, которые создаются на этапе инициализации программы, появятся в рамках основного окна сразу же после запуска приложения. Это не всегда желательно. Например, дочернее окно для отображения текстового документа имеет смысл показывать только после того, как пользователь решил открыть такой документ и выбрал соответствующий файл. По этой причине дочерние формы обычно убирают из списка инициализации форм основного файла проекта (см. п.3 в указаниях к работе). Их инициализация в этом случае обычно проводится непосредственно перед отображением дочерней формы на экране. Если пользователь из предыдущего примера решил открыть текстовый документ, то реакция на это событие будет включать в себя следующие строки программного кода:

{

         ...

         Определяем, какой файл хочет открыть пользователь

         ...

}

// Создаем дочернюю форму. Параметр конструктора формы – владелец

// создаваемого объекта, в данном случае – это сама основная форма

TForm *w = new TForm2(this);

{

         ...

         Работаем с указателем на объект формы:

         проводим загрузку содержания выбранного файла в форму и т.п.

         ...

}

// отображаем форму на экране

w->Show();

        

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

4.                 Ранее уже говорилось, что стандартным способом закрытия SDI-формы является ее исчезновение с экрана. При этом объект формы продолжает существовать. Поскольку дочерние MDI-формы не могут быть невидимыми, то попытка закрыть дочернюю форму приложения приведет к ее минимизации в рамках основного окна. Чтобы убрать форму с экрана и освободить занимаемую ее объектом память, необходимо для этой формы написать обработчик события OnClose, в котором значение параметра Action устанавливается равным caFree. Таким образом, объект формы будет создаваться в тот момент, когда соответствующее дочернее окно потребовалось пользователю и уничтожаться сразу после того, как это окно было закрыто.

5.                 Для организации главного меню в основной форме приложения следует использовать визуальный компонент MainMenu. Каждый пункт/подпункт главного меню представляет собой объект класса TMenuItem. Если свойство WindowMenu основной формы MDI-приложения будет содержать указатель на объект TMenuItem, соответствующий некоторому пункту главного меню, то при запуске приложения в этом пункте меню будет автоматически формироваться список открытых дочерних окон.

6.                 Кроме того, для основной формы приложения можно вызывать различные методы упорядочения дочерних форм и управления ими:

·                    Метод Cascade() – Расположение дочерних форм каскадом;

·                    Метод Tile() – Расположение окон «черепицей» («мозаикой»), для задания способа упорядочения (по вертикали или по горизонтали) используется свойство формы TileMode;

·                    Метод ArrangeIcons() – Упорядочение иконок свернутых дочерних форм;

·                    Метод Next() – Активируется следующее дочернее окно;

·                    Метод Previous() – Активируется предыдущее дочерние окно.

Методы Next() и Previous() предполагают работу со списком дочерних форм. Этот список изменяется в процессе работы приложения – каждая вновь созданная дочерняя форма попадает в конец списка. У программиста есть возможность работать со списком дочерних форм непосредственно. Для этого используются свойства основной формы MDIChildCount и MDIChildren. Свойство MDIChildren – представляет собой список указателей на объекты открытых дочерних форм, а MDIChildCount определяет их количество.

7.                 Реализацию многих элементов MDI-интерфейса взяли на себя разработчики среды C++ Builder. В частности, программисту не надо беспокоиться за стандартные назначения определенных комбинаций клавиш – эти требования будут выполняться для его приложения автоматически.

 

На сегодняшний день нет единого мнения относительно того, какой из двух подходов к организации пользовательского интерфейса –  SDI или MDI – лучше. Долгое время считалось, что SDI можно использовать только в небольших программах, а для приложений с большим количеством окон необходимо применение MDI. В последнее время, наоборот, стали говорить о том, что SDI является более гибким подходом к проектированию пользовательского интерфейса, так как в мультидокументных приложениях отсутствует возможность быстрого переключения между дочерними окнами. Некоторые специалисты даже рекомендуют разработчикам отказываться от проектирования и реализации MDI-приложений, несмотря на то, что разработка сложных многооконных SDI-приложений обычно требует больших временных затрат (по сравнению с аналогичным MDI-приложением). В этой связи интересным представляется подход разработчиков продукта Microsoft Office. Первые версии программных продуктов этого пакета имели SDI-интерфейс, потом использовался MDI-интерфейс, а начиная с версии Microsoft Office 2000 – снова SDI. Однако многие элементы многодокументного интерфейса (привычные сочетания клавиш, пункт Window (Окно) и др.) при этом были сохранены. Думается, что такой подход, основанный на грамотном сочетании двух методов организации пользовательского интерфейса, является оправданным.

 елает это автоматически!

Просмотрено: 0%
Просмотрено: 0%
Скачать материал
Скачать материал "Лекции по дисциплине "ОСНОВЫ АЛГОРИТМИЗАЦИИ И ПРОГРАММИРОВАНИЯ ""

Получите профессию

HR-менеджер

за 6 месяцев

Пройти курс

Рабочие листы
к вашим урокам

Скачать

Выбранный для просмотра документ Лекция 2 Лексика языка программирования С++ .doc

ТЕМА: Лексика языка программирования С++ Пробельные символы. Операции. Ключевые слова. Знаки пунктуации и специальные символы.

ТИП: лекция

ЦЕЛИ :

Учебная :

·       изучить особенности написания программы на языке Си в различных программных средах;

·       определить отличительные особенности каждой программной среды;

Развивая :

·       • развивать логическое мышление , внимание , память ;

·       • развивать кругозор .

Воспитательная :

• развивать познавательный интерес к предмету.

Структура занятия

1 . Организационный момент ( 3 мин )

2 . Сообщения темы , цели занятия ( 5 мин )

3 . Актуализация знаний ( 15 мин )

4 . Выдача теоретического материала ( 30 мин )

5 . Проверка полученных знаний ( 10 мин )

6 . Подведение итогов , выставление оценок ( 5 мин )

7 . Выдача домашнего задания ( 2 мин )

Литература.

1.     Шилдт Г. С++: базовый курс, 3-е издание.: Пер. с англ.-М. : Издательский дом "Вильямс", 2010

2.     Архангельский А. Я. "Програмирование в C++ Builder". - М.: "Издательство Бином", 2003

3.     Деннис Ритчи "Язык программирования C. 2-е издание, переработанное и дополненное" Пер. с англ.-М. : Издательский дом "Вильямс", 2009

4.     Керниган Б. "Язык программирования Си"-Питер. Невский Диалект, 2009

5.     Вильямс А. Системное программирование в Windows 2000 для профессионалов - СПб: Питер, 2003. - 624 с.: ил.

6.     Юркин А. Задачник по программированию. — СПб.: Питер, 2002. — 192 с.

Вопрос актуализации знаний:

1.     Дайте определение языку программирования.

2.     Какие языки программирования вы знаете.

3.     Какие уровни языков программировании

План

1. Введение в C и C ++. 2

2. Базовые средства языка C++. 3

2.1 Состав языка. 3

2.2 Алфавит языка С (С++) 6

2.3 Лексемы.. 6

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

1.     Какие особенности написания программы для Microsoft Visual Studio?

2.     Какие особенности написания программы для C++ Builder?

3.     Как подключается заголовочный файл?

1. Введение в C и C ++

Язык C разработан Денисом Ричи в начале 80-х г.г. Этот язык создавался как язык системного программирования. Язык C эффективен для разработки операционных систем, компиляторов и т.д., более удобен для написания прикладных программ. Язык поддерживает полный набор конструкций структурного программирования, поддерживает модульность, имеет простую структуру программ. Кроме того, язык C обладает набором низкоуровневых средств, которые позволяют иметь удобный доступ к аппаратным средствам компьютера, в частности, позволяют добраться до каждого бита памяти. алгоритмический программа лексема константа

Преимущества C: переносимость C-программ компьютеры различной архитектуры, из одной операционной системы в другую, лаконичность записи алгоритмов, возможность получить эффективный код программы. Первое описание C приведено в книги Кернигана и Ричи. Имеется стандарт языка CANSI. Гибкость и универсальность C обеспечило его широкое распространение.

В начале 80-х г.г. Бьёрн Страуструп расширил C, он создал язык C с классами. В 1983 году это название было заменено на C ++. В 1998 году был создан стандарт языка C ++ - ISO/IEC 14882. Язык C ++ полностью включает возможности языка C, т.е. C – программа свободно реализуется в C ++.

2. Базовые средства языка C++

2.1 Состав языка

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

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

• Алфавит языка, или его символы — это основные неделимые знаки, с помощью которых пишутся все тексты на языке.

• Лексема, или элементарная конструкция, — минимальная единица языка, имеющая самостоятельный смысл.

• Выражение задает правило вычисления некоторого значения.

• Оператор задает законченное описание некоторого действия.

Рисунок 1. Состав алгоритмического языка

Для описания сложного действия требуется последовательность операторов. Операторы могут быть объединены в составной оператор, или блок (Блоком в языке С++- считается последовательность операторов, заключенная в фигурные скобки { }). В этом случае они рассматриваются как один оператор. Операторы бывают исполняемые и неисполняемые. Исполняемые операторы задают действия над данными. Неисполняемые операторы служат для описания данных, поэтому их часто называют операторами описания или просто описаниями.

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

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

Для того чтобы выполнить программу, требуется перевести ее на язык, понятный процессору — в машинные коды. Этот процесс состоит из нескольких этапов. Рисунок 1.2 иллюстрирует эти этапы для языка С++.

Сначала программа (текстовый файл с расширением имя.cpp) передается препроцессору, который выполняет директивы, содержащиеся в ее тексте (например, включение в текст так называемых заголовочных файлов — текстовых файлов, в которых содержатся описания используемых в программе элементов).

Получившийся полный текст (файл с расширением .cpp) программы поступает на вход компилятора, который выделяет лексемы, а затем на основе грамматики языка распознает выражения и операторы, построенные из этих лексем. При этом компилятор выявляет синтаксические ошибки и в случае их отсутствия строит объектный модуль.( создается файл – имя.obj).

Компоновщик, или редактор связей, формирует исполняемый модуль программы, подключая к объектному модулю другие объектные модули, в том числе содержащие функции библиотек, обращение к которым содержится в любой программе (например, для осуществления вывода на экран). Если программа состоит из нескольких исходных файлов, они компилируются по отдельности и объединяются на этапе компоновки.

Исполняемый модуль имеет расширение имя.ехе и запускается на выполнение обычным образом.

 

Рисунок 1.2. Этапы создания исполняемой программы

Для описания языка в документации часто используется некоторый формальный метаязык, например, формулы Бэкуса—Наура или синтаксические диаграммы. Для наглядности и простоты изложения будем использовать широко распространенный неформальный способ описания, при котором необязательные части синтаксических конструкций заключаются в квадратные скобки, текст, который необходимо заменить конкретным значением, пишется по-русски, а выбор одного из нескольких элементов обозначается вертикальной чертой.

Например, запись

[ void | int ] имя():

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

2.2 Алфавит языка С (С++)

Алфавит языка С (С++) включает в себя:

1.      Прописные и строчные буквы латинского алфавита и знак подчёркивания

2.      Цифры от 0 до 9

3.       Специальные знаки: " { } , | [ ] ( ) + - / % * . \ ? < = > ! & # ~ ; ' '

4.      Пробельные символы: пробел, символы табуляции, символ перехода на следующую строку.

2.3 Лексемы

Из символов алфавита формируются лексемы:

1.            идентификаторы

2.            ключевые (зарезервированные) слова

3.            знаки операций

4.            константы

5.            разделители

Идентификаторы – имя программного объекта. Используются латинские буквы, цифры, знак подчеркивания. Первый символ имени – буква или знак подчеркивания. Пробелов не должно быть, длина имени не ограничивается. В Borland C++ -- 1-32 символов. Идентификатор не должен совпадать с ключевыми словами.

Ключевые слова – слова, имеющие специальные значения для компилятора.

!!! Все ключевые слова пишутся только строчными буквами.

Примеры некоторых ключевых слов:

asm class inline return

auto double int static

bool do new this

break enum operator try

case friend public typedef

Знаки операций – один или более символов, определяющих действия над операндами.

Знаки операций делятся на:

·                   унарные

·                   бинарные

·                   терарные

Один и тот же знак может интерпретироваться по-разному, в зависимости от контекста.

Константы – неизменяемые величины. Различают целые, вещественные, символьные и строковые константы. Тип константы определяется её записью.

Целая константа может быть записана в 8-, 10-, 16-ричном формате. В 10-ричном формате константы начинаются не с нуля (8, 10, 0, 7, 15 и т.д.). В 8-ричном формате константа начинается с нуля, далее следуют 8-ричные цифры (01, 07, 0701 и т.д.). В 16-ричном формате константа начинается с 0X (0XA, 0X777, 0X1 и т.д.).

Вещественная константа может быть записана в следующем виде:

[цифры].[цифры]

Например: 2.2 или .01 и т.д.

или в экспоненциальной форме

Записывается в виде:

[цифры][.][ цифры]{E|e}[+|-][ цифры]

Примеры записи:

0.2E5

.1e-5

10E5

Символьная константа – один или более символов в апострофах. Примеры:

`A’ `\n’ `\0’ `\0x17’ и др.

Символьные константы, состоящие из одного символа, занимают в памяти один байт и имеют стандартный тип char. Двухсимвольные константы занимают два байта и имеют тип int, при этом первый символ размещается в байте с меньшим адресом.

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

• кодов, не имеющих графического изображения (например, \а — звуковой сигнал, \n — перевод курсора в начало следующей строки);

• символов апострофа ( ' ), обратной косой черты ( \ ), знака вопроса ( ? ) и кавычки ( " );

• любого символа с помощью его шестнадцатеричного или восьмеричного кода, например, \073, \0xF5. Числовое значение должно находиться в диапазоне от 0 до 255.

Последовательности символов, начинающиеся с обратной косой черты, называют управляющими, или escape последовательностями.

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

Таблица 1.1 Управляющие последовательности

Запись

Код шестнадцатеричный

Название

\a

7

Звуковой сигнал

\b

8

Возврат на шаг

\f

C

Перевод страницы(формата)

\n

A

Перевод строки

\r

D

Возврат каретки

\t

9

Горизонтальная табуляция

\v

B

Вертикальная табуляция

\\

5C

Обратная косая черта

\’

27

Апостроф

\”

22

Кавычка

\?

3F

Знак вопроса

\0ddd

-

Восьмеричный код символа

\0xddd

ddd

Шестнадцатеричный код символа

 

Приведенные управляющие константы используются в строковых константах.

Строковые константы – последовательность символов, взятых в кавычки.

Примеры:

“Привет”

 “\n y=%d x=%d

 “фирма \“Гарант\” ”

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

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

Например, строка

"Условие задачи: \

найти сумму положительных чисел, \

делящихся на 2"

полностью эквивалентна строке

"Условие задачи: найти сумму положительных чисел, делящихся на 2"

В конец каждого строкового литерала компилятором добавляется нулевой символ, представляемый управляющей последовательностью \0. Поэтому длина строки всегда на единицу больше количества символов в ее записи. Таким образом, пустая строка "" имеет длину 1 байт.

Разница между строкой из одного символа, например, "А", и символьной константой 'А' в том, что строка занимает 2 байта, а символьная константа занимает 1 байт.

Пустая символьная константа недопустима.

Разделители – пробелы, точки с запятой, фигурные скобки.

В тексте программы можно использовать комментарии. Они выделяются следующим образом:

/*комментарий*/

либо с каждой строки

// комментарий

Просмотрено: 0%
Просмотрено: 0%
Скачать материал
Скачать материал "Лекции по дисциплине "ОСНОВЫ АЛГОРИТМИЗАЦИИ И ПРОГРАММИРОВАНИЯ ""

Получите профессию

Фитнес-тренер

за 6 месяцев

Пройти курс

Рабочие листы
к вашим урокам

Скачать

Выбранный для просмотра документ Лекция 3 Скалярные типы данных. Целые типы. Вещественные типы. Переменные и константы. Объявления переменных.doc

ТЕМА: Скалярные типы данных.  Целые типы. Вещественные типы. Переменные и константы.  Объявления переменных.

ТИП: комбинированное занятие.

ЦЕЛИ :

Учебная :

·        изучить основные типы данных.

·        научиться задавать переменные в С++

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

Развивая :

·        • развивать логическое мышление , внимание , память ;

·        • развивать кругозор .

Воспитательная :

·        • развивать познавательный интерес к предмету.

·       Структура занятия

·       1 . Организационный момент ( 3 мин )

·       2 . Сообщения темы , цели занятия ( 5 мин )

·       3 . Актуализация знаний ( 10 мин )

·       4 . Выдача теоретического материала ( 20 мин )

·       5 . Проверка полученных знаний на практике ( 35 мин )

·       6 . Подведение итогов , выставление оценок ( 5 мин )

·       7 . Выдача домашнего задания ( 2 мин )

Литература.

1.     Шилдт Г. С++: базовый курс, 3-е издание.: Пер. с англ.-М. : Издательский дом "Вильямс", 2010

2.     Архангельский А. Я. "Програмирование в C++ Builder". - М.: "Издательство Бином", 2003

3.     Деннис Ритчи "Язык программирования C. 2-е издание, переработанное и дополненное" Пер. с англ.-М. : Издательский дом "Вильямс", 2009

4.     Керниган Б. "Язык программирования Си"-Питер. Невский Диалект, 2009

5.     Вильямс А. Системное программирование в Windows 2000 для профессионалов - СПб: Питер, 2003. - 624 с.: ил.

6.     Юркин А. Задачник по программированию. — СПб.: Питер, 2002. — 192 с.

Вопрос актуализации знаний:

1.     Какие системы счисления вы знаете?

2.     Как записывается число в компьютере.

3.     Как выделяется память под переменые

4.     Назначение регистров

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

1.     Когда возникает необходимость в организации развилки?

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

3.     Выражение какого типа может выступать в качестве условия при организации развилки? Какие значения принимают такие выражения?

4.     Могут ли в полной развилке не выполниться операторы ни по одной из ветвей? выполниться по обеим ветвям?

5.     В каком случае целесообразно использовать оператор выбора?

6.     Какого типа может быть выражение, являющееся селектором выбора? Приведите примеры.

7.     Приведите пример оператора выбора, где выражение-селектор выбора имеет перечислимый тип.

План.

Концепция типа данных. 1

Простые типы данных. 1

Целый тип (int) 2

Символьный тип (char) 2

Расширенный символьный тип (wchar_t) 2

Логический тип (bool) 2

Типы с плавающей точкой (float, double и longdouble) 2

Тип void. 3

Концепция типа данных

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

Тип данных определяет:

·                                 внутреннее представление данных в памяти компьютера;

·                                 множество значений, которые могут принимать величины этого типа;

·                                 операции и функции, которые можно применять к величинам этого типа.

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

Все типы языка С++ можно разделить на простые (скалярные), составные (агрегатные) и функциональные. Простые типы могут быть стандартными и определенными программистом.

В языке С++ определено шесть стандартных простых типов данных для представления целых, вещественных, символьных и логических величин. На основе этих типов, а также массивов и указателей (указатель не является самостоятельным типом, он всегда связан с каким-либо другим конкретным типом), программист может вводить описание собственных простых или структурированных типов. К структурированным типам относятся перечисления, функции, структуры, объединения и классы.

Простые типы данных

Простые типы делятся на целочисленные типы и типы с плавающей точкой. Для описания стандартных типов определены следующие ключевые слова:

·                                 int (целый);

·                                 char (символьный);

·                                 wchar_t (расширенный символьный);

·                                 bool (логический);

·                                 float (вещественный);

·                                 double (вещественный с двойной точностью).

Существует четыре спецификатора типа, уточняющих внутреннее представление и диапазон значений стандартных типов:

·                                 short (короткий);

·                                 long (длинный);

·                                 signed (со знаком);

·                                 unsigned (без знака).

Целый тип (int)

Размер типа int стандартом ANSI не определяется. Он зависит от реализации. Для 16-разрядного процессора под величины этого типа отводится 2 байта, для 32-разрядного — 4 байта.

Спецификатор short перед именем типа указывает компилятору, что под число требуется отвести 2 байта. Спецификатор long означает, что целая величина будет занимать 4 байта.

Внутреннее представление величины целого типа — целое число в двоичном коде. При использовании спецификатора signed старший бит числа интерпретируется как знаковый ( 0 — положительное число, 1 — отрицательное). Спецификатор unsigned позволяет представлять только положительные числа. Диапазоны значений величин целого типа с различными спецификаторами для IBM PC-совместимых компьютеров приведены в таблице 1.4.

По умолчанию все целочисленные типы считаются знаковыми.

Константам, встречающимся в программе, приписывается тип в соответствии с их видом. Программист может явно указать требуемый тип с помощью суффиксов L, l (long) и U, u (unsigned). Например, константа 32L имеет тип long и занимает 4 байта.

Типы shortint,longint,signedint иunsignedint можно сокращать до short,long, signed иunsignedсоответственно.

Символьный тип (char)

Под величину символьного типа отводится количество байт, достаточное для размещения любого символа из набора символов для данного компьютера. Как правило, это 1 байт.

Тип char, как и другие целые типы, может быть со знаком или без знака.

В величинах со знаком можно хранить значения в диапазоне от –128 до 127. При использовании спецификатора unsignedзначения могут находиться в пределах от 0 до 255. Величины типа char применяются также для хранения целых чисел, не превышающих границы указанных диапазонов.

Расширенный символьный тип (wchar_t)

Тип wchar_t предназначен для работы с набором символов, для кодировки которых недостаточно 1 байта, например, Unicode. Размер этого типа зависит от реализации; как правило, он соответствует типу short.

Логический тип (bool)

Величины логического типа могут принимать только значения true и false. Внутренняя форма представления значения false — 0 (нуль). Любое другое значение интерпретируется как true. При преобразовании к целому типу true имеет значение 1.

Типы с плавающей точкой (float, double и longdouble)

Стандарт С++ определяет три типа данных для хранения вещественных значений: float, double и longdouble.

Внутреннее представление вещественного числа состоит из мантиссы и порядка. Длина мантиссы определяет точность числа, а длина порядка — его диапазон.

Константы с плавающей точкой имеют по умолчанию тип double. Можно явно указать тип константы с помощью суффиксов F, f (float) и L, l (long). Например, константа 2E+6L будет иметь типlongdouble.

Таблица 1.3. Диапазоны значений простых типов данных для IBM PC

Тип

Диапазон значений

Размер (байт)

Bool

true и false

1

signed char

–128 … 127

1

Unsigned char

0 … 255

1

signed short int

–32 768 … 32 767

2

Unsigned short int

0 … 65 535

2

signed long int

–2 147 483 648 … 2 147 483 647

4

Unsigned long int

0 … 4 294 967 295

4

Float

3.4e–38 … 3.4e+38

4

Double

1.7e–308 … 1.7e+308

8

long double

3.4e–4932 … 3.4e+4932

10

Для вещественных типов в таблице приведены абсолютные величины минимальных и максимальных значений.

Тип void

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

Просмотрено: 0%
Просмотрено: 0%
Скачать материал
Скачать материал "Лекции по дисциплине "ОСНОВЫ АЛГОРИТМИЗАЦИИ И ПРОГРАММИРОВАНИЯ ""

Получите профессию

Няня

за 6 месяцев

Пройти курс

Рабочие листы
к вашим урокам

Скачать

Выбранный для просмотра документ Лекция 4 Операции и выражения. Арифметические операции. Операции отношения. Логические операции. Операции присваивания. .doc

ТЕМА: Операции и выражения. Арифметические  операции. Операции отношения. Логические операции. Операции присваивания.

ТИП: комбинированное занятие.

ЦЕЛИ :

Учебная :

·        изучить способы задания переменных.

·        научиться использовать основные операции.

·        научиться строить простые выражения

Развивая :

·        • развивать логическое мышление , внимание , память ;

·        • развивать кругозор .

Воспитательная :

·        • развивать познавательный интерес к предмету.

·       Структура занятия

·       1 . Организационный момент ( 3 мин )

·       2 . Сообщения темы , цели занятия ( 5 мин )

·       3 . Актуализация знаний ( 10 мин )

·       4 . Выдача теоретического материала ( 20 мин )

·       5 . Проверка полученных знаний на практике ( 35 мин )

·       6 . Подведение итогов , выставление оценок ( 5 мин )

·       7 . Выдача домашнего задания ( 2 мин )

Литература.

1.     Шилдт Г. С++: базовый курс, 3-е издание.: Пер. с англ.-М. : Издательский дом "Вильямс", 2010

2.     Архангельский А. Я. "Програмирование в C++ Builder". - М.: "Издательство Бином", 2003

3.     Деннис Ритчи "Язык программирования C. 2-е издание, переработанное и дополненное" Пер. с англ.-М. : Издательский дом "Вильямс", 2009

4.     Керниган Б. "Язык программирования Си"-Питер. Невский Диалект, 2009

5.     Вильямс А. Системное программирование в Windows 2000 для профессионалов - СПб: Питер, 2003. - 624 с.: ил.

6.     Юркин А. Задачник по программированию. — СПб.: Питер, 2002. — 192 с.

 

Вопрос актуализации знаний:

Дайте определение понятию переменой.

Как объявляются переменные.

Базовые типы данных

Простые арифметические операции

 

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

Дайте определение области действия идентификатора.

Дайте определение класс памяти.

Что такое типизированная константа?

Опишите основные операции и их применение.

Что такое выражение?

План

Переменные. 2

Операции. 4

Выражения. 7

Арифметические операции с числами. 7

Инкремент и декремент. 8

Сокращенные арифметические формы. 9

Математические функции языка С# 10

 

 

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

Операнды задают данные для вычислений.

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

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

Переменные

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

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

Переменная может быть объявлена многократно, но определена только в одном месте программы.

Для определения переменных применяется оператор описания следующего формата:

[класс памяти] [const] тип имя [инициализатор];

В одном операторе можно описать несколько переменных одного типа, разделяя их запятыми.

Модификатор const показывает, что значение переменной нельзя изменять во время выполнения программы. Такую переменную называют типизированной константой. Она должна быть инициализирована при объявлении. Инициализатор можно записывать в двух формах — со знаком равенства или в круглых скобках:

= значение 
( значение )

Примеры описания переменных:

short int a = 1;
char s, symbol = 'f'; /* инициализация относится только к symbol */
char t = 54;
float c = 0.22, x, sum;
const char C = 'C';

Если тип инициализирующего значения не совпадает с типом переменной, выполняются преобразования типа.

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

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

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

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

Класс памяти определяет время жизни и область видимости программного объекта.

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

Время жизни может быть постоянным (в течение выполнения программы) и временным (в течение выполнения блока).

Для задания класса памяти используются следующие спецификаторы:

autoавтоматическая переменная. Память под нее в стеке выделяется и при необходимости инициализируется каждый раз при выполнении оператора, содержащего ее определение, и освобождается при выходе из блока, в котором она описана. Время ее жизни — локальное.

extern — переменная определяется в другом месте программы. Используется для создания переменных, доступных во всех модулях программы, где они объявлены. Если переменная в том же операторе инициализируется, спецификатор extern игнорируется.

staticстатическая переменная. Время жизни — постоянное. Инициализируется один раз при первом выполнении оператора, содержащего определение переменной. В зависимости от расположения оператора описания статические переменные могут быть глобальными и локальными. Глобальные статические переменные видны только в том модуле, в котором они описаны.

register — аналогично auto, но память выделяется по возможности в регистрах процессора.

int a;//1 глобальная переменная a main()
{ int b;//2 локальная переменная b
   extern int x;//3 переменная х определена позже
     static int c;//4 локальная статическая переменная c
    a = 1;//5 присваивание глобальной переменной
   int a;//6 локальная переменная a
   a = 2;//7 присваивание локальной переменной
    ::a = 3;//8 присваивание глобальной переменной 
}
int x = 4;//9 определение и инициализация x 

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

Имя переменной должно быть уникальным в своей области действия.

Операции

В таблице 1.5 приведено большинство операций, определенных в языке С++, в соответствии с их приоритетами (по убыванию приоритетов, операции с разными приоритетами разделены чертой).

Таблица 1.5 Основные операции языка С++

Операция

Краткое описание

Унарные операции

 

++

увеличение на 1

– –

уменьшение на 1 (пробелы между символами не допускаются)

sizeof

размер

~

поразрядное отрицание

!

логическое отрицание

арифметическое отрицание (унарный минус)

+

унарный плюс

&

взятие адреса

*

разадресация

new

выделение памяти

delete

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

(type)

преобразование типа

Бинарные операции

 

*

умножение

/

деление

%

остаток от деления

+

сложение

вычитание

<< 

сдвиг влево

>> 

сдвиг вправо

меньше

<=

меньше или равно

больше

>=

больше или равно

==

равно

!=

не равно

&

поразрядная конъюнкция (И)

^

поразрядное исключающее ИЛИ

|

поразрядная дизъюнкция (ИЛИ)

&&

логическое И

||

логическое ИЛИ

? :

условная операция

=

присваивание

*=

умножение с присваиванием

/=

деление с присваиванием

%=

остаток отделения с присваиванием

+=

сложение с присваиванием

–=

вычитание с присваиванием

<<=

сдвиг влево с присваиванием

>>=

сдвиг вправо с присваиванием

&=

поразрядное И с присваиванием

|=

поразрядное ИЛИ с присваиванием

^=

поразрядное исключающее ИЛИ с присваиванием

,

последовательное вычисление

Операции увеличения и уменьшения на 1 (++ и --). Эти операции, называемые также инкрементом и декрементом, имеют две формы записи — префиксную, когда операция записывается перед операндом, и постфиксную. В префиксной форме сначала изменяется операнд, а затем его значение становится результирующим значением выражения, а в постфиксной форме значением выражения является исходное значение операнда, после чего он изменяется.

Операндом операции инкремента в общем случае является так называемое L-значение (L-value). Так обозначается любое выражение, адресующее некоторый участок памяти, в который можно занести значение. Переменная является частным случаем L-значения.

Операции отрицания (–, ! и ~). Арифметическое отрицание (унарный минус –) изменяет знак операнда целого или вещественного типа на противоположный.

Логическоеотрицание (!) дает в результате значение 0, если операнд есть истина (не нуль), и значение 1, если операнд равен нулю. Операнд должен быть целого или вещественного типа или типа указатель.

Поразрядное отрицание (~), часто называемое побитовым, инвертирует каждый разряд в двоичном представлении целочисленного операнда.

Деление (/) и остаток от деления (%). Операция деления применима к операндам арифметического типа. Если оба операнда целочисленные, результат операции округляется до целого числа, в противном случае тип результата определяется правилами преобразования.

Операция остатка от деления применяется только к целочисленным операндам. Знак результата зависит от реализации.

Операции отношения ( <, <=, >, >=, = =, != ) сравнивают первый операнд со вторым. Операнды могут быть арифметического типа или указателями. Результатом операции является значение true или false. Операции сравнения на равенство и неравенство имеют меньший приоритет, чем остальные операции сравнения.

Поразрядные операции (&, |, ^) применяются только к целочисленным операндам и работают с их двоичными представлениями. При выполнении операций операнды сопоставляются побитово (первый бит первого операнда с первым битом второго, второй бит первого операнда со вторым битом второго, и т.д.).

Логические операции (&& и ||). Операнды логических операций И (&&) и ИЛИ (||) могут иметь арифметический тип или быть указателями, при этом операнды в каждой операции могут быть различных типов.

Преобразования типов не производятся, каждый операнд оценивается с точки зрения его эквивалентности нулю (операнд, равный нулю, рассматривается как false, не равный нулю — как true). Результатом логической операции является true или false.

Логические операции выполняются слева направо.

Операции присваивания (=, +=, -=, *= и т.д.). Операции присваивания могут использоваться в программе как законченные операторы. К операциям они относятся потому, что могут использоваться в выражениях и формируют результат своего выполнения.

Формат операции простого присваивания (=):

операнд_1 = операнд_2

Первый операнд должен быть L-значением, второй — выражением. Сначала вычисляется выражение, стоящее в правой части операции, а потом его результат записывается в область памяти, указанную в левой части.

В сложных операциях присваивания ( +=, *=, /= и т.п.) при вычислении выражения, стоящего в правой части, используется и L-значение из левой части, например, при сложении с присваиванием ко второму операнду прибавляется первый, и результат записывается в первый операнд.

Условная операция (?:). Эта операция тернарная, то есть имеет три операнда. Ее формат:

операнд_1 ? операнд_2 : операнд_3

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

Если результат вычисления операнда 1 равен true, то результатом условной операции будет значение второго операнда, иначе — третьего операнда.

Выражения

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

Примеры выражений:

(a + 0.12)/6
x && y || !z
(t * sin(x)-1.05e4)/((2 * k + 2) * (2 * k + 3))

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

Если в одном выражении записано несколько операций одного приоритета, унарные операции, условная операция и операции присваивания выполняются справа налево, остальные — слева направо.

Порядок вычисления подвыражений внутри выражений не определен.

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

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

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

 

Арифметические операции с числами.

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

Название операции

Символ, применяемый для обозначения в языке С.

Краткое описание. Пример.

Сложение

+

Складывает два значения вместе, результатом является сумма операндов: 5+18 результат 23

Вычитание

-

Вычитает значение, находящееся справа из значения, находящегося слева от оператора. Результат – разность операндов: 20-15 результат 5

Умножение

*

Перемножает два значения, результатом является произведение операндов: 5*10 результат 50

Деление

/

Делит значение, находящееся слева на значение, находящееся справа от оператора. Например: 20/4 результат 5

Деление по модулю

%

Результатом этой операции является остаток от целочисленного деления, например, если мы делим 11 на 3, то целых частей у нас получается 3, (так как 3*3=9), в остатке будет 2, это число и будет результатом деления по модулю:
11/3 = 3 целых 2 в остатке
11%3 = 2 (остаток)

Инкремент и декремент.

Все вышеописанные операции, являлись бинарными, однако существуют еще и унарные арифметические операции, таких операций в школьном курсе нет, хотя на самом деле они очень просты:

1.Инкремент – обозначается конструкцией ++. Данный оператор увеличивает содержимое любой переменной на единицу и перезаписывает значение переменной. Например,

int a=8;

cout<<a; // на экране число 8

a++;

cout<<a; // на экране число 9

2.Декремент – обозначается конструкцией --. Данный оператор уменьшает содержимое любой переменной на единицу и перезаписывает значение переменной. Например,

int a=8;

cout<<a; // на экране число 8

a--;

cout<<a; // на экране число 7

Достаточно просто, не правда ли?! Такие выражения могут быть представлены и так: a=a+1 или a=a-1. Следует отметить, что для литералов ни инкремент, ни декремент не используются, т. к. совершенно не логично поступать следующим образом 5=5+1. Это явная ошибка. Однако на этом мы не закончим знакомство с инкрементом и декрементом. В прошлом разделе урока мы выяснили, что синтаксис унарного оператора, может быть не только таким

операнд оператор;

, но и таким

оператор операнд;

Такие формы записи носят название постфиксной, (оператор располагается после значения) и префиксной (оператор располагается до значения). И инкремент, и декремент обладают обеими формами. Давайте разберемся, какие есть различия между формами, и в каких случаях эти различия имеют значение.

Пример 1.

int a=8;

cout<<a; // на экране число 8

a++;

cout<<a; // на экране число 9

++a;

cout<<a; // на экране число 10

В данном примере нет никакой разницы, между префиксной и постфиксной формой. И в первом и во втором случае значение переменной а просто увеличивается на единицу. Смысл использования различных форм оператора появляется только тогда, когда в строке кроме самого оператора, есть еще какая-нибудь команда.

Пример 2.

int a=8;

cout<<++a; // на экране число 9

cout<<a++; // на экране число 9

cout<<a; // на экране число 10

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

1. Все команды в языке С выполняются справа налево.

2. Если кроме постфиксной формы инкремента или декремента, в строке есть еще какая-либо команда, то сначала выполняется эта команда, и только потом инкремент или декремент независимо от расположения команд в строке.

3. Если кроме префиксной формы инкремента или декремента, в строке есть еще какая-либо команда, то все команды в строке выполняются справа налево согласно приоритету операторов.

Теперь более подробно о примере:

• Изначально значение переменной равно числу 8.

• Команда cout<<++a; содержит префиксную форму оператора инкремент, следовательно, используя третье правило, описанное выше, мы сначала увеличиваем значение переменной а на единицу, а затем показываем его на экран с помощью команды cout<<.

• Команда cout<<a++; содержит постфиксную форму оператора инкремент, следовательно, используя второе правило, описанное выше, мы сначала показываем значение переменной (всё еще 9) на экран с помощью команды cout<<, а затем увеличиваем значение переменной a на единицу.

• При выполнении следующей команды cout<<a; будет показано уже измененное (увеличенное) значение, то есть число 10.

Сокращенные арифметические формы.

Исходя из предыдущих тем данного раздела урока, мы с вами теперь знаем, как упростить неудобную и «некрасивую» запись типа х=х+1 или х=х-1, превратив её в х++, или х--. Но таким образом, мы можем увеличивать и уменьшать значение переменной лишь на единицу, а как быть с любым другим числом? Например, как упростить запись:

Х=Х+12;

В данном случае, тоже есть простое решение – использовать так называемые комбинированные операторы или сокращенные арифметические формы. Выглядят они следующим образом:

Название формы

Комбинация

Стандартная запись

Сокращенная запись

Присваивание с умножением

*=

А=А*N

A*=N

Присваивание с делением

/=

A=A/N

A/=N

Присваивание с делением по модулю

%=

A=A%N

A%=N

Присваивание с вычитанием

-=

A=A-N

A-=N

Присваивание со сложением

+=

A=A+N

A+=N

Мы рекомендуем вам в дальнейшем пользоваться сокращенными формами, так как это не только является хорошим тоном в программировании, но и значительно повышает читабельность программного кода. Кроме того, в некоторых источниках упоминается о том, что сокращенные формы обрабатываются компьютером быстрее, повышая скорость выполнения программы.

 Математические функции языка С#

С# содержит большое количество встроенных математических функций, которые реализованы в классе Math пространства имен System.

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

Замечание. Использование нескольких функций с одним и тем же именем, но с различными типами параметров, называется перегрузкой функции. Например, функция Math.Abs(), вычисляющая модуль числа, имеет 7 перегруженных версий: double Math.Abs (double x), float Math.Abs (float x), int Math.Abs(int x), и т.д.

Название

Описание

1.

Math.Abs(<выражение>)

Модуль

2.

Math.Ceiling(<выражение>)

Округление для большего целого

3.

Math.Cos(<выражение>)

Косинус

4.

Math.Е

Число е

5.

Math.Exp(<выражение>)

Экспонента

6.

Math.Floor(<выражение>)

Округление до меньшего целого

7.

Math.Log(<выражение>)

Натуральный логарифм

8.

Math.Log10(<выражение>)

Десятичный логарифм

9.

Math.Max(<выражение1>, <выражение2>)

Максимум из двух значений

10.

Math.Min(<выражение1>, <выражение2>)

Минимум из двух значений

11.

Math.PI

Число

12.

Math.Pow(<выражение1>, <выражение2>)

Возведение в степень

13.

Math.Round(<выражение>)

Простое округление

14.

Math.Sign(<выражение>)

Знак числа

15.

Math.Sin(<выражение>)

Синус

16.

Math.Sqrt(<выражение>)

Квадратный корень

17.

Math.Тan(<выражение>)

Тангенс

 

 

Просмотрено: 0%
Просмотрено: 0%
Скачать материал
Скачать материал "Лекции по дисциплине "ОСНОВЫ АЛГОРИТМИЗАЦИИ И ПРОГРАММИРОВАНИЯ ""

Получите профессию

Менеджер по туризму

за 6 месяцев

Пройти курс

Рабочие листы
к вашим урокам

Скачать

Выбранный для просмотра документ Лекция 5 Программирование ветвлений. Программирование циклов .doc

ТЕМА Программирование ветвлений. Программирование циклов.

ТИП: комбинированное занятие.

ЦЕЛИ :

Учебная :

·        изучить программы использующие алгоритм ветвления..

·        научиться применять оператор IF в программах

·        научиться применять оператор SWITH в программах

·        научиться  рисовать блок – схему алгоритмов ветвления

Развивая :

·        • развивать логическое мышление , внимание , память ;

·        • развивать кругозор .

Воспитательная :

·        • развивать познавательный интерес к предмету.

·       Структура занятия

·       1 . Организационный момент ( 3 мин )

·       2 . Сообщения темы , цели занятия ( 5 мин )

·       3 . Актуализация знаний ( 10 мин )

·       4 . Выдача теоретического материала ( 20 мин )

·       5 . Проверка полученных знаний на практике ( 35 мин )

·       6 . Подведение итогов , выставление оценок ( 5 мин )

·       7 . Выдача домашнего задания ( 2 мин )

Литература.

1.     Шилдт Г. С++: базовый курс, 3-е издание.: Пер. с англ.-М. : Издательский дом "Вильямс", 2010

2.     Архангельский А. Я. "Програмирование в C++ Builder". - М.: "Издательство Бином", 2003

3.     Деннис Ритчи "Язык программирования C. 2-е издание, переработанное и дополненное" Пер. с англ.-М. : Издательский дом "Вильямс", 2009

4.     Керниган Б. "Язык программирования Си"-Питер. Невский Диалект, 2009

5.     Вильямс А. Системное программирование в Windows 2000 для профессионалов - СПб: Питер, 2003. - 624 с.: ил.

6.     Юркин А. Задачник по программированию. — СПб.: Питер, 2002. — 192 с.

Вопрос актуализации знаний:

1.     Какие логические операции вы знаете?

2.     Как создаются логические выражения.

3.     Основные блоки блок - схем

4.     Что такое алгоритм ветвления

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

1.     Когда возникает необходимость в организации развилки?

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

3.     Выражение какого типа может выступать в качестве условия при организации развилки? Какие значения принимают такие выражения?

4.     Могут ли в полной развилке не выполниться операторы ни по одной из ветвей? выполниться по обеим ветвям?

5.     В каком случае целесообразно использовать оператор выбора?

6.     Какого типа может быть выражение, являющееся селектором выбора? Приведите примеры.

7.     Используя оператор выбора решить задачу: "Определить знак заданного целого числа".

8.     Приведите пример оператора выбора, где выражение-селектор выбора имеет перечислимый тип.

План

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

1.1 Форма сокращенного оператора if: 2

1.2 Форма полного оператора if: 3

2. Оператор выбора switch. 5

3. Цикл for 8

4. Цикл while. 12

 

Операторы ветвления позволяют изменить порядок выполнения операторов в программе. К операторам ветвления относятся условный оператор if и оператор выбора switch.

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

Условный оператор if используется для разветвления процесса обработки данных на два направления. Он может иметь одну из форм: сокращенную или полную.

1.1 Форма сокращенного оператора if:

if (B)  S;

где В - логическое или арифметическое выражение, истинность которого проверяется; S - оператор: простой или составной.

При выполнении сокращенной формы оператора if сначала вычисляется выражение B, затем проводится анализ его результата: если B истинно, то выполняется оператор S; если B ложно, то оператор S пропускается. Таким образом, с помощью сокращенной формы оператора if можно либо выполнить оператор S, либо пропустить его.

1.2 Форма полного оператора if:

if (B) S1; else S2;

где B - логическое или арифметическое выражение, истинность которого проверяется; S1, S2- оператор: простой или составной.

При выполнении полной формы оператора if сначала вычисляется выражение B, затем анализируется его результат: если B истинно, то выполняется оператор S1, а оператор S2 пропускается; если B ложно, то выполняется оператор S2, а S1 - пропускается. Таким образом, с помощью полной формы оператора if можно выбрать одно из двух альтернативных действий процесса обработки данных.

Рассмотрим несколько примеров записи условного оператора if:

if (a > 0) x=y;               // Сокращенная форма c простым оператором 
if (++i) {x=y; y=2*z;}               // Сокращенная форма c составным оператором
if (a > 0 || b<0) x=y; else  x=z;   // Полная форма с простым оператором
if (i+j-1) { x= 0; y= 1;} else {x=1; y:=0;}           // Полная форма с составными операторами

Рассмотрим пример использования условного оператора.

static void Main()
{
  Console.Write("x= ");
  float x = float.Parse(Console.ReadLine());
            Console.Write("y=");
  float y = float.Parse(Console.ReadLine());
  if (x < y ) Console.WriteLine("min= "+x);
  else Console.WriteLine("min= "+y);
}

Результат работы программы:

x          y          min
0          0          0
1          -1         -1
-2         2          -2

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

Операторы S1 и S2 могут также являться операторами if. Такие операторы называют вложенными. При этом ключевое слово else связывается с ближайшим предыдущим словом if, которое еще не связано ни с одним else. Рассмотрим пример программы, использующей вложенные условные операторы.

Пример: Дана мишень. 04_01

Подсчитать количество очков после выстрела по данной мишени.

static void Main()
{
  int Ball=0;
            Console.Write("x= ");
  float x = float.Parse(Console.ReadLine());
  Console.Write("y= ");
  float y = float.Parse(Console.ReadLine());
  if (x * x + y * y <=1) Ball = 10;           //окружность с радиусом 1
  else  if (x * x + y * y <= 4) Ball = 5;     //окружность с радиусом 2
  Console.WriteLine("Ball= "+ Ball);
}

Результат работы программы:

x          y          Ball
0          0          10
1          -1         5
-2         2          0

Задание. Измените программу так, чтобы подсчитывалось количество очков для мишени вида 04_02

2. Оператор выбора switch

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

switch ( <выражение> )
{ 
  case <константное_выражение_1>: 
   [<оператор 1>];  <оператор перехода>;
  case <константное_выражение_2>: 
   [<оператор 2>]; <оператор перехода>; 
  ...
  case <константное_выражение_n>: 
   [<оператор n>]; <оператор перехода>;
   [default: <оператор>; ] 
}

Замечание. Выражение, записанное в квадратных скобках, является необязательным элементом в операторе switch. Если оно отсутствует, то может отсутствовать и оператор перехода.

Выражение, стоящее за ключевым словом switch, должно иметь арифметический, символьный, строковый тип или тип указатель. Все константные выражения должны иметь разные значения, но их тип должен совпадать с типом выражения, стоящим после switch или приводиться к нему. Ключевое слово case и расположенное после него константное выражение называют также меткой case.

Выполнение оператора начинается с вычисления выражения, расположенного за ключевым словом switch. Полученный результат сравнивается с меткой case. Если результат выражения соответствует метке case, то выполняется оператор, стоящий после этой метки, за которым обязательно должен следовать оператор перехода: break, goto и т.д. При использовании оператора break происходит выход из switch и управление передается оператору, следующему за switch. Если же используется оператор goto, то управление передается оператору, помеченному меткой, стоящей после goto.

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

static void Main()
{
  Console.Write("OPER= ");
  char oper=char.Parse(Console.ReadLine());
  bool ok=true;
  Console.Write("A= ");
  int a=int.Parse(Console.ReadLine());
  Console.Write("B= ");            
  int b=int.Parse(Console.ReadLine());
  float res=0;
  switch (oper)
  {
    case '+': res = a + b; break;     //1
    case '-': res = a - b; break;
    case '*': res = a * b; break;
    case ':': if (b != 0)
    { 
      res = (float)a / b; break;
    }
    else goto default;
    default: ok = false; break;        
  }
  if (ok) Console.WriteLine("{0} {1} {2} = {3}", a, oper, b, res);
  else Console.WriteLine("error");
}

Результат выполнения программы:

oper     x          y          rez
+          4          5          9
:           4          0          error
%         4          3          error

Задания.

1.     Замените в строке 1 оператор break, на оператор goto case '-' и посмотрите, что произойдет, если в качестве операции ввести +.

2.     В условном операторе if уберите ветку else и посмотрите, что произойдет.

Если необходимо, чтобы для разных меток выполнялось одно и тоже действие, то метки перечисляются через двоеточие. Например:

switch (oper)
{
  case '+': res = a + b; break;       
  case '-': res = a - b; break;
  case '*': res = a * b; break;
  case '/': case ':': if (b != 0)  // перечисление меток
  {
    res = (float)a / b; break;
  }
  else goto default;
  default: ok = false; break;
}

Цикл for

Цикл for используется для организации циклов - повторения каких-либо однородных действий. Например, если вам нужно посчитать сумму чисел от 1 до 10, то вы должны сложить 1 и 2, полученную сумму сложить с 3, полученную сумму сложить с 4 и так далее, пока не получим сумму предыдущих чисел с 10. В итоге получили последовательность повторяющихся действий: к сумме предыдущих чисел прибавляем следующее число. Вот для организации таких действий и используются циклы, в частности цикл for.

Вот общий вид цикла for:

 

            for (начальная_инструкция; условие; выражение)

            {

                        инструкции;

            }

 

Семантика (смысл) цикла for такова, что сначала выполняется начальная_инструкция; она инициализует переменную, используемую в цикле. Затем проверяется условие. Если оно истинно, то выполняются инструкции, вычисляется выражение, и управление передается обратно в начало цикла for с той разницей, что начальная_инструкция уже не выполняется. Это продолжается до тех пор, пока условие не станет ложно, после чего управление передается следующей_инструкции. Каждый проход цикла называется итерацией цикла.

Начальной_инструкцией может быть инструкция-выражение или просто объявление.

Цикл for является итерационной инструкцией, используемой обычно с увеличивающейся или уменьшающейся переменной. Например, в следующем коде инструкция for используется для сложения целых чисел от 1 до 10.

sum = 0;

 

for (i = 1; i <= 10; ++i)

 

sum += i;

Когда инструкция for начинает выполняться, управляющей переменной i задается начальное значение 1. Затем проверяется условие продолжения цикла i <= 10. Поскольку начальное значение i равно 1, это условие удовлетворяется, так что оператор тела инструкции суммирует к значению переменной sum, равному 0, значение счетчика i, равное 1. Затем управляющая переменная i увеличивается на единицу в выражении ++i и цикл опять начинается с проверки условия его продолжения. Поскольку значение i теперь 2, предельная величина не превышена, так что программа снова выполняет тело цикла. Этот процесс продолжается, пока управляющая переменная i не увеличится до 11 — это приведет к тому, что условие продолжения цикла нарушится и повторение прекратится. Выполнение программы продолжится с первого оператора, расположенного после цикла for.

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

for (sum = 0,i = 1; i <= 10; ++i)

            sum += i;

Основное назначение использования оператора запятая — помочь программисту использовать несколько выражений задания начальных значений и (или) несколько выражений приращения переменных. Например, в одной структуре for может быть несколько управляющих переменных, которым надо задавать начальное значение и которые надо изменять. Например:

for(i=0,j=0;i<3,j<`4;i++,j+=2)

 

cout<<i*j;

Данный цикл проведет две итерации, после которых значение счетчика i станет равным 2, а значение счетчика j = 4. При этом условие для второго счетчик не выполняется (т.к. j строго должен быть меньше 4) и цикл будет прерван. На экране будет выведено 02.

В цикле for может присутствовать локальное объявление переменной управления циклом, как в следующем примере.

for (int i = 0; i < N; ++i)

            sum += i*i;

Целая переменная i теперь является объявленной в программе. Это может вносить путаницу, поэтому лучше объявлять все программные переменные в начале блока.

В большинстве случаев инсрукцию for можно представить при помощи инструкции while:

 

начальная_инструкция;

 

while (условие) {

 

            инструкция;

 

            выражение;

 

            }

 

следующая_инструкция;

 

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

for (i = 1, sum = 0 ; ; sum += i++ )

            cout << sum << endl;

Размещение точки с запятой сразу после правой закрывающей скобки заголовка for делает тело структуры пустым оператором. Обычно это логическая ошибка.

“Приращение” инструкции for может быть отрицательным (в этом случае в действительности происходит не приращение, а уменьшение переменной, управляющей циклом).

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

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

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

Давайте рассмотрим несколько вариантов применения цикла for:

а) Изменение управляющей переменной от 1 до 100 с шагом 1.

 

for (int i = 1; i <= 100; i++)

b) Изменение управляющей переменной от 100 до 1 с шагом -1

(с уменьшением на 1).

 

for (int i = 100; i >= 1; i--)

Распространенная ошибка при программировании, это использование несоответствующей операции отношения в условии продолжения цикла при счете циклов сверху вниз (например, использование i <= 1 при счете циклов сверху до 1 не включая).

c) Изменение управляющей переменной от 7 до 77 с шагом 7.

 

for (int i = 0; i <= 77; i += 7)

d) Изменение управляющей переменной от 20 до 2 с шагом -2.

 

for (int i = 20; i >= 2; i -= 2)

e) Изменение управляющей переменной в следующей последовательности:

2, 5, 8, 11, 14.

 

for (int j = 2;j <= 14; j += 3)

f) Изменение управляющей переменной в следующей последовательности:

99, 88, 77, 66, 55, 44, 33, 22, 11, 0.

for (int j = 99; j >= 0; j -= 11)

Цикл while.

Обобщенная форма цикла while:

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

Вначале вычисляется выражение. Если результат отличен от нуля (true), тогда выполняется оператор и управление переходит обратно к началу цикла while. Это приводит к выполнению тела цикла while, а именно оператора, который будет выполняться до тех пор, пока выражение не станет равным нулю (false). Затем управление передается следующему оператору. Таким образом, цикл может выполняться ноль или более раз. Например:

/* Пример выводит на экрон 5 строк типа "Строка" + "индекс" +

"выводится в цикле", где "индекс" меняется от 0 до 4 */ 

 

#include < iostream.h >

void main()

{  

int i = 0; /*Объявление и инициализация переменной i*/ 

cout << "\n Начало цикла"; 

while (i != 5) /*Проверяется выражение (i != 5),

если результат - истина, выполняется операторы тела цикла,

в противном случае управление передается оператору, следующему за циклом. */

{

cout << "Строка " << i << "выводится в цикле \n";

i++;

}

cout << "\n Оператор, следующий за циклом";

Чтобы материал стал более понятным рассмотрим еще такой пример:

/*Программа выводит на экран данные таблицы умножения на 2*/

#include < iostream.h >

void main()

{

int i = 0;

cout << "Таблица умножения на 2 \n";

while ( i ++ < 10)

cout << i << " * 2 = " << i * 2 << '\n';

cout << "\n Все";

Давайте остановимся на операторе while в данном примере и по шагам посмотрим, как он работает.

while ( i ++ < 10)

cout << i << " * 2 = " << i * 2 << '\n';

Цикл состоит из двух частей: условие цикла и тело цикла. Обратите внимание на условие цикла - это выражение i++ < 10 . Условие гласит, что тело цикла будет выполняться пока выполняется условие i < 10 . ПОСЛЕ проверки этого условия значение переменной i увеличивается на 1 (об этом говорит оператор i++). Тело цикла состоит всего из одного оператора, а именно:

cout << i << " * 2 = " << i * 2 << '\n';

Итак, 1-й шаг цикла

1.1 Значение переменной i равно 0 (так она была проинициализирована).

1.2 Проверка условия i < 10 дает истина (т.к. 0 < 10)

1.3 Значение переменной i увеличивается на 1, теперь i = 1.

1.4 Так как проверка условия цикла дала значение истина управление

передается оператору тела цикла, т.е. на экран выводится строка 1 * 2 = 2

1.5 Далее управление передается циклу while

2-й шаг цикла

2.1 Значение переменной i равно 1.

2.2 Результат проверки условия цикла - истина (1 < 10)

2.3 Значение переменной i увеличивается на 1, теперь i = 2.

2.4 Так как проверка условия цикла дала значение истина управление

передается оператору тела цикла, т.е. на экран выводится строка 2 * 2 = 4

2.5 Далее управление передается циклу while

9-й шаг цикла

9.1 Значение переменной i равно 8.

9.2 Результат проверки условия цикла - истина (8 < 10)

9.3 Значение переменной i увеличивается на 1, теперь i = 9.

9.4 Так проверка условия цикла дала значение истина управление

передается оператору тела цикла, т.е. на экран выводится строка 9 * 2 = 18

9.5 Далее управление передается циклу while

10-й шаг цикла

10.1 Значение переменной i равно 9.

10.2 Результат проверки условия цикла - истина ( 9 < 10)

10.3 Значение переменной i увеличивается на 1, теперь i = 10.

10.4 Так проверка условия цикла дала значение истина управление

передается оператору тела цикла, т.е. на экран выводится строка 10 * 2 = 20

10.5 Далее управление передается циклу while

11-й шаг цикла

11.1 Значение переменной i равно 10.

11.2 Результат проверки условия цикла - ложь ( 10 равно 10, а не меньше!)

11.3 Значение переменной i увеличивается на 1, теперь i = 11.

11.4 Так проверка условия цикла дала значение ложь, управление

НЕ передается в тело цикла, т.е. выполнение цикла заканчивается,

и управление переходит к оператору, следующему за while,

т.е. к cout << "\n Все";

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

Написать программу

 

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

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

3.     Создать программу, которая выводит на экран простые числа в диапазоне от 2 до 1000. (Число называется простым, если оно делится только на 1 и на само себя без остатка; причем числа 1 и 2 простыми не считаются).

4.             числе n; находит сумму цифр числа n; меняет порядок цифр числа n на обратный

 

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

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

3.     Создать программу, которая выводит на экран простые числа в диапазоне от 2 до 1000. (Число называется простым, если оно делится только на 1 и на само себя без остатка; причем числа 1 и 2 простыми не считаются).

4.     Дано произвольное целое число n. Написать программу, которая разбивает число n на цифры и выводит их на экран; подсчитывает сколько цифр в числе n; находит сумму цифр числа n; меняет порядок цифр числа n на обратный

1.     Определить и вывести на печать номер квадранта, в котором расположена точка M(x,y).

2.     Даны действительные числа X, Y. Меньшее из этих двух чисел заменить их полусуммой, а большее - их удвоенным произведением. Результат вычисления вывести на экран монитора.

3.     Даны три действительных числа. Возвести в квадрат те из них, значения которых неотрицательны. Результат вычисления вывести на экран монитора. <=0;

4.     Написать программу выбора наибольшего из трёх чисел.

5.     Даны x, y. Если x и y отрицательны, то каждое значение заменить его модулем; если отрицательно только одно из них, то оба значения увеличить на 0.5; если оба значения неотрицательны, то оба значения увеличить в 10 раз.

6.     Выяснить, принадлежит ли точка M(x,y) кругу радиуса r с центром в точке с координатами a,b.

7.     Определить, принадлежит ли точка M(x,y) кольцу с центром в начале координат, внешним радиусом R1, и внутренним радиусом R2.

8.     Даны три числа a, b, c. Выяснить, верно ли, что a<b<c.
Ответ получить в текстовой форме: верно или неверно.

9.     Определить, является ли частное чисел a и b, округлённое до ближайшего целого чётным числом.

 

Просмотрено: 0%
Просмотрено: 0%
Скачать материал
Скачать материал "Лекции по дисциплине "ОСНОВЫ АЛГОРИТМИЗАЦИИ И ПРОГРАММИРОВАНИЯ ""

Получите профессию

Копирайтер

за 6 месяцев

Пройти курс

Рабочие листы
к вашим урокам

Скачать

Выбранный для просмотра документ Лекция 6 Массивы. Одномерные и многомерные массивы. Сортировка массивов. Методы поиска элементов в массивах.doc

ТЕМА Массивы. Одномерные и многомерные массивы. Сортировка массивов. Методы поиска элементов в массивах.

ТИП: комбинированное занятие.

ЦЕЛИ :

Учебная :

·        изучить способы задания массива.

·        научиться применять массивы в программах

Развивая :

·        • развивать логическое мышление , внимание , память ;

·        • развивать кругозор .

Воспитательная :

·        • развивать познавательный интерес к предмету.

·       Структура занятия

·       1 . Организационный момент ( 3 мин )

·       2 . Сообщения темы , цели занятия ( 5 мин )

·       3 . Актуализация знаний ( 10 мин )

·       4 . Выдача теоретического материала ( 20 мин )

·       5 . Проверка полученных знаний на практике ( 35 мин )

·       6 . Подведение итогов , выставление оценок ( 5 мин )

·       7 . Выдача домашнего задания ( 2 мин )

Литература.

1.     Шилдт Г. С++: базовый курс, 3-е издание.: Пер. с англ.-М. : Издательский дом "Вильямс", 2010

2.     Архангельский А. Я. "Програмирование в C++ Builder". - М.: "Издательство Бином", 2003

3.     Деннис Ритчи "Язык программирования C. 2-е издание, переработанное и дополненное" Пер. с англ.-М. : Издательский дом "Вильямс", 2009

4.     Керниган Б. "Язык программирования Си"-Питер. Невский Диалект, 2009

5.     Вильямс А. Системное программирование в Windows 2000 для профессионалов - СПб: Питер, 2003. - 624 с.: ил.

6.     Юркин А. Задачник по программированию. — СПб.: Питер, 2002. — 192 с.

Вопрос актуализации знаний:

1.     Дайте определение вектору?

2.     Дайте определение матрицы.

3.     Основные способы заполнения матриц

4.     Опишите основные виды циклов

5.     Какие типы данных Вы знаете?

6.      Перечислите и приведите примеры простых типов данных.

7.      Перечислите сложные типы данных.

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

1.     Что такое массивы?

2.     Что называют элементом массива?

3.      Что называют индексом элемента массива?

4.     Сколько элементов может содержать массив?

5.     Сколько индексов может быть у одного элемента массива?

6.     Элементы какого типа может содержать массив?

7.     Какие типы данных допустимы для индексов элементов массива?

План

Описание синтаксиса. 2

Вывод элементов массива через цикл. 4

Объявление массива без инициализации. 4

Заполнение массива с клавиатуры.. 5

. Многомерные массивы.. 6

. Инициализация многомерных массивов. 6

Размещение массивов в свободной памяти. 6

Связь указателей и массивов. 7

Массивы символов. 8

. Функции для работы с массивами символов. 8

 

Описание синтаксиса

Массив создается почти так же, как и обычная переменная. Для хранения десяти фамилий нам нужен массив, состоящий из 10 элементов. Количество элементов массива задается при его объявлении и заключается в квадратные скобки.

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

Попробуем вывести наш массив на экран с помощью оператора cout.

#include <iostream>
#include <string>
 
int main()    
{
    std::string students[10] = {
        "Иванов", "Петров", "Сидоров",
        "Ахмедов", "Ерошкин", "Выхин",
        "Андеев", "Вин Дизель", "Картошкин", "Чубайс"
    };
    std::cout << students << std::endl; // Пытаемся вывести весь массив непосредственно
    return 0;
}

Скомпилируйте этот код и посмотрите, на результат работы программы. Готово? А теперь запустите программу еще раз и сравните с предыдущим результатом. В моей операционной системе вывод был следующим:

  • Первый вывод: 0x7ffff8b85820
  • Второй вывод: 0x7fff7a335f90
  • Третий вывод: 0x7ffff847eb40

Мы видим, что выводится адрес этого массива в оперативной памяти, а никакие не «Иванов» и «Петров».

Дело в том, что при создании переменной, ей выделяется определенное место в памяти. Если мы объявляем переменную типа int, то на машинном уровне она описывается двумя параметрами — ее адресом и размером хранимых данных.

Массивы в памяти хранятся таким же образом. Массив типа int из 10 элементов описывается с помощью адреса его первого элемента и количества байт, которое может вместить этот массив. Если для хранения одного целого числа выделяется 4 байта, то для массива из десяти целых чисел будет выделено 40 байт.

Так почему же, при повторном запуске программы, адреса различаются? Это сделано для защиты от атак переполнения буфера. Такая технология называется рандомизацией адресного пространства и реализована в большинстве популярных ОС.

Попробуем вывести первый элемент массива — фамилию студента Иванова.

#include <iostream>
#include <string>
 
int main()
{    
    std::string students[10] = {
        "Иванов", "Петров", "Сидоров",
        "Ахмедов", "Ерошкин", "Выхин",
        "Андеев", "Вин Дизель", "Картошкин", "Чубайс"
    };
    std::cout << students[0] <<  std::endl;
    return 0;
}

Смотрим, компилируем, запускаем. Убедились, что вывелся именно «Иванов». Заметьте, что нумерация элементов массива в C++ начинается с нуля. Следовательно, фамилия первого студента находится в students[0], а фамилия последнего — в students[9].

В большинстве языков программирования нумерация элементов массива также начинается с нуля.

Попробуем вывести список всех студентов. Но сначала подумаем, а что если бы вместо группы из десяти студентов, была бы кафедра их ста, факультет из тысячи, или даже весь университет? Ну не будем же мы писать десятки тысяч строк с cout?

Вывод элементов массива через цикл

#include <iostream>
#include <string>
 
int main()
{
    std::string students[10] = {
        "Иванов", "Петров", "Сидоров",
        "Ахмедов", "Ерошкин", "Выхин",
        "Андеев", "Вин Дизель", "Картошкин", "Чубайс"
    };  
    for (int i = 0; i < 10; i++) {
        std::cout << students[i] << std::endl;
    }
 
    return 0;
}

Если бы нам пришлось выводить массив из нескольких тысяч фамилий, то мы бы просто увеличили конечное значение счетчика цикла — строку for (...; i < 10; ...) заменили на for (...; i < 10000; ...).

Заметьте что счетчик нашего цикла начинается с нуля, а заканчивается девяткой. Если вместо оператора строгого неравенства — i < 10 использовать оператор «меньше, либо равно» — i <= 10, то на последней итерации программа обратится к несуществующему элементу массива — students[10]. Это может привести к ошибкам сегментации и аварийному завершению программы. Будьте внимательны — подобные ошибки бывает сложно отловить.

Массив, как и любую переменную можно не заполнять значениями при объявлении.

Объявление массива без инициализации

string students[10];
// или
string teachers[5];

Элементы такого массива обычно содержат в себе «мусор» из выделенной, но еще не инициализированной, памяти. Некоторые компиляторы, такие как GCC, заполняют все элементы массива нулями при его создании.

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

int n;
cin >> n;
string students[n]; /* Неверно */

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

Заполним с клавиатуры пустой массив из 10 элементов.

Заполнение массива с клавиатуры

#include <iostream>
#include <string>
 
using std::cout;
using std::cin;
using std::endl;
 
int main()
{    
        int arr[10];
 
        // Заполняем массив с клавиатуры
        for (int i = 0; i < 10; i++) {
            cout << "[" << i + 1 << "]" << ": ";
            cin >> arr[i];
        }
 
        // И выводим заполненный массив.
        cout << "\nВаш массив: ";
 
        for (int i = 0; i < 10; ++i) {
            cout << arr[i] << " ";
        }
 
        cout << endl;
 
        return 0;
}

Скомпилируем эту программу и проверим ее работу.

. Многомерные массивы

Можно создать массивы, которые имеют более чем одну размерность. Каждая размерность представляется в виде индекса массива. Следовательно, двухмерные массивы имеют два индекса; трехмерные массивы имеют три индекса; и т.д. Массивы могут иметь любую размерность, хотя наиболее вероятно, что большинство массивов, которые используются в программе, будут одно или двухмерными

Хорошим примером двухмерного массива является шахматная доска. Одна размерность представляет 8 строк, другая размерность представляет восемь столбцов.

Предположим, что имеется класс с названием SQUARE. Тогда можно следующим образом описать массив с названием Board, который соответствует шахматной доске

SQUARE Board[8][8];

. Инициализация многомерных массивов

Многомерные массивы также можно инициализировать. При этом нужно учитывать, что при инициализации последующий индекс массива изменяется быстрее, чем предыдущий. В случае двухмерного массива,  сначала устанавливается номер строки 0 (первый индекс), а затем номер столбца будет меняться от начального значения до конечного, и только потом номер строки будет увеличен. Например, для массива:

int Array[3][2];

первые три элемента при инициализации попадут в первую строку Array[0]; следующие три - во вторую Array[1] и т.д. Этот массив можно инициализировать таким образом:

int Array[3][2] = {1,2,3,4,5,6};

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

int Array[3][2] = {{1,2},{3,4},{5,6}};

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

Размещение массивов в свободной памяти

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

Dog *Family = new Dog[500];

объявляется указатель Family, который содержит адрес первого элемента массива размером 500. Другими словами, Family указывает на нулевой элемент Family[0].

Преимущество использования указателя Family состоит в том, что можно использовать ссылочную арифметику, чтобы получить доступ к каждому члену массива Family. Например, можете написать

Dog *Family = new Dog [500];

Dog *pDog = Family;//pDog указывает на Family[0]

pDog->SetAge(10);  //задаем возраст объекту Family[0]

pDog++;            //переходим к Family[1]

pDog->SetAge(20); //задаем возраст объекту Family[1]

Здесь объявляется новый массив из 500 объектов класса Dog и указатель хранит адрес первого элемента массива. Используя этот указатель, для первого объекта вызывается функция SetAge(). Затем указатель инкрементируется, для того чтобы он указывал на следующий элемент массива. Затем для второго элемента массива также вызывается функция SetAge().

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

Family[2].SetAge(10);

 

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

delete [] pDog;

Квадратные скобки сообщают компилятору, что будет удаляться массив значений. Если скобки опустить, то из памяти будет удален только первый элемент массива.

Связь указателей и массивов

В C++ имя массива является константным указателем на первый элемент массива. Следовательно, в объявлении

Dog  Family[50];

имя Family является константным указателем, хранящим значение &Family[0], что является адресом первого элемента массива Family.

Разрешается использовать имена массивов в качестве константных указателей и указателей в качестве имен массивов. Следовательно, Family+4 является допустимым способом доступа к значению в элементе массива Family[4].

Компилятор выполняет все арифметические преобразования, когда к указателю добавлятся значение, например, увеличивается на единицу. Адрес, который получит указатель, когда пишется Family+4 не будет соответствовать адресу на 4 байта больше чем адрес, который хранится в переменной Family, это будет адрес четвертого объекта массива. Если каждый объект длиной 4 байта, то при записи Family+4 к адресу в Family будет добавлено 16 байт. Если объектами массива являются объекты класса Dog, которые имеют четыре члена-данных типа long (длиной по 4 байта), и два члена-данных типа short (длиной по 2 байта), то каждый объект данного класса Dog имеет длину в 20 байт. В этом случае значением Family+4 является адрес на 80 байт больше чем адрес начала массива. Такое изменение адресов называется адресной арифметикой.

Массивы символов

Строка это последовательность символов. До сих пор мы работали только со строками, которые были текстовыми константами, заключенными в двойные кавычки ("). Например:

cout << "hello world.\n";

В C++ строки можно хранить в массивах типа char. Последним элементом строки обязательно должен быть код 0 (не символ, а число). Такие массивы называются "С-строками”. Можно описать и инициализировать строку точно так же, как объявляется любой массив. Например:

char Greeting[] = {’H’,’e’,’l’,’l’,’o’,’ ’,’W’, ’o’,’r’,’l’,’d’, 0 };

Последним элементом в списке инициализации стоит число (код символа) 0,  с помощью которого многие функции в языке C++ находят конец строки. Хотя выше приведенный способ инициализации символьного массива работает, но он достаточно трудоемок для записи. В языке имеется другой, более удобный, способ инициализации символьного массива, пример которого показан ниже.

char Greeting[] = "Hello World";

Следует сделать два замечания по используемому здесь синтаксису:

·        вместо использования символьных констант, выделенных одиночными кавычками ('), здесь используется символьная строка, выделенная двойными кавычками (") и она не заключена в фигурные скобки;

·        в конце строки не добавляется число 0, так как компилятор добавит его сам.

Размер массива Greeting должен быть не менее 12 элементов, чтобы сохранить эту строку: 11 элементов для хранения букв и один элемент для хранения завершающего строку нуля.

. Функции для работы с массивами символов

Язык C++ наследовал от языка C набор функций для работы с массивами символов. Все эти функции объявлены в заголовочном файле cstring. Если программа использует такие функции, то этот файл нужно включить в программу:

#include <cstring>

Примерами таких функций являются:

·                    int strlen(str) - определяет количество символов в массиве, не включая нулевой код конца строки;

·                    char* strcpy(str1,str2) – копирует все символы до нуля из символьного массива str2 в символьный массив str1;

·                    char* strcat(str1,str2) – добавляет содержимое символьного массива str2 к концу строки в символьном массиве str1 (конкатенаця); массив str1 должен иметь достаточно места для хранения всех символов;

·                    int strcmp(str1,str2)- сравнивает поэлементно строки в символьных массивах str1 и str2 в соответствии с алфавитным порядком; если очередной символ в str1 по алфавитному порядку следует ранее, чем соответствующий символ в str2, то функция возвращает отрицательное значение; если строки совпадают, возвращается 0; если очередной символ в str1 следует по алфавиту после соответствующего символа в str2 , то функция возвращает положительное значение;

·                    и т.п.

В примере 11.2 показано использование стандартных функций для работы с С-строками.

Пример 11.2. Использование функций для работы со строками.

 1:#include <iostream>// для потоков ввода-вывода

 2:#include <cstring> // для работы с С-строками

 3:using namespace std;

 4:int main()

 5:{

 6:  char first_name[20], last_name[40], full_name[70];

 7:  cout << "Enter your first name - "; // имя

 8:  cin >> first_name;  // например, Bart

 9:  cout << "Enter your last name - "; // фамилия

10:  cin >> last_name;  // например, Simpson

11:  strcpy(full_name, last_name);// копируем фамилию

12:  strcat(full_name, ", "); // добавляем запятую и пробел

13:  strcat(full_name, first_name); // добавляем имя

14:  int len = strlen(full_name);   // длина строки

15:  cout<<"Your full name is " << full_name << endl;

16:  cout<<"which contains ”<<len<<" characters."<<endl;

17:  return 0;

18:}

Результат работы программы:

Enter your first name - Bart

Enter your last name – Simpson

Your full name is Simpson, Bart

which contains 13 characters.

В строке 2 в программу включен заголовочный файл cstring, в котором объявлены функции для работы с символьными массивами. В строке 6 объявляются три символьных массива размерами в 20, 40 и 70 символов. Программист должен следить за тем, чтобы эти размеры не были превышены при работе программы. Такая проверка в данной программе не делается для того, чтобы сделать ее проще. В строках 11-14 вызываются функции стандартной библиотеки, для выполнения операций над строками. Конечно такая запись операций не очень понятная и удобная.

Данный пример с использованием нового типа данных string, переписан в разделе 12.4. Из сравнения этих программ можно увидеть, насколько могут быть полезными новые пользовательские типы данных.

 

В заголовочном файле <cstdlib> определены полезные функции для преобразования строк, представляющих численные значения в сами численные значения:

double atof(const char* p);// преобразует строку в p в double

int atoi(const char* p);// преобразует строку в p в int

long atol(const char* p);// преобразует строку в p в long

 

Например:

char p[] = “12.85”; // строка текста

double d = atof(p); // d получает числовое значение 12.85

 

Такие преобразования могут например использоваться при работе с параметрами командной строки (смотри раздел 14.7).

 

Написать программу

1.                 Подсчитайте среднее арифметическое элементов массива. Количество элементов равно 10 и значения элементов задаются с клавиатуры пользователем.

2.                 Подсчитайте сумму нечетных элементов массива и количество элементов, значение которых равно нулю. Размер массива 10 элементов, значения которых задаются с клавиатуры пользователем.

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

4.                 Написать программу меняющую порядок следования элементов массива на противоположный (то есть первый элемент становится последним, а последний - первым; второй элемент становится предпоследним, а предпоследний - вторым и так далее) и выводящую результирующий массив на экран. Элементы массива вводятся пользователем с клавиатуры.

5.                 Подсчитайте среднее арифметическое элементов массива. Количество элементов равно 10 и значения элементов задаются с клавиатуры пользователем.

6.                 Подсчитайте сумму нечетных элементов массива и количество элементов, значение которых равно нулю. Размер массива 10 элементов, значения которых задаются с клавиатуры пользователем.

7.                 Предложите пользователю ввести с клавиатуры 10 целых чисел, сохраните их в массиве и выведите на экран номера тех элементов массива, значение которых кратно 3.

8.                 Написать программу меняющую порядок следования элементов массива на противоположный (то есть первый элемент становится последним, а последний - первым; второй элемент становится предпоследним, а предпоследний - вторым и так далее) и выводящую результирующий массив на экран. Элементы массива вводятся пользователем с клавиатуры.

 

Просмотрено: 0%
Просмотрено: 0%
Скачать материал
Скачать материал "Лекции по дисциплине "ОСНОВЫ АЛГОРИТМИЗАЦИИ И ПРОГРАММИРОВАНИЯ ""

Получите профессию

Фитнес-тренер

за 6 месяцев

Пройти курс

Рабочие листы
к вашим урокам

Скачать

Выбранный для просмотра документ Лекция 7 Указатели и массивы. Массивы указателей, динамические массивы. .doc

 

ТЕМА Указатели и массивы. Массивы указателей, динамические массивы.

ТИП: комбинированное занятие.

ЦЕЛИ :

Учебная :

·        изучить способы задания указателя.

·        Научиться использовать указатели в программах

Развивая :

·        • развивать логическое мышление , внимание , память ;

·        • развивать кругозор .

Воспитательная :

·        • развивать познавательный интерес к предмету.

·       Структура занятия

·       1 . Организационный момент ( 3 мин )

·       2 . Сообщения темы , цели занятия ( 5 мин )

·       3 . Актуализация знаний ( 10 мин )

·       4 . Выдача теоретического материала ( 20 мин )

·       5 . Проверка полученных знаний на практике ( 35 мин )

·       6 . Подведение итогов , выставление оценок ( 5 мин )

·       7 . Выдача домашнего задания ( 2 мин )

Литература.

1.     Шилдт Г. С++: базовый курс, 3-е издание.: Пер. с англ.-М. : Издательский дом "Вильямс", 2010

2.     Архангельский А. Я. "Програмирование в C++ Builder". - М.: "Издательство Бином", 2003

3.     Деннис Ритчи "Язык программирования C. 2-е издание, переработанное и дополненное" Пер. с англ.-М. : Издательский дом "Вильямс", 2009

4.     Керниган Б. "Язык программирования Си"-Питер. Невский Диалект, 2009

5.     Вильямс А. Системное программирование в Windows 2000 для профессионалов - СПб: Питер, 2003. - 624 с.: ил.

6.     Юркин А. Задачник по программированию. — СПб.: Питер, 2002. — 192 с.

Вопрос актуализации знаний:

1.     Дайте определение адреса?

2.     Что такое адресация.

3.     Выделение памяти

4.     Структура организации памяти

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

1.     Какие операции можно применять к указателям?

2.     . Для чего и как происходит динамическое распределение памяти?

3.     . Что такое Esc-последовательность?

4.     . Для чего используются индексные выражения?

5.     . Каким образом выделяется память под массивы?

6.     . Что общего между массивами и указателями?

7.     . Как располагаются в памяти элементы многомерного массива??

 

План.

1.Основные понятия об указателях

2.Объявление указателей и основные операции над ними

3.Многоуровневая адресация

4.Операции над указателями

5.Проблеммы, связанные с указателями

 

1.Основные понятия об указателях

Язык Си отличается от других структурированных немашинных языков широким использованием указателей. В определённой степени именно наличие в языке Си указателей сделало его очень удобным для системного программирования. Указатели обеспечивают доступ к адресам переменных в памяти. Они позволяют работать с символическими адресами (именами переменных, содержащих адреса) и выполнение над адресами ряда операций. С помощью указателей например можно:

·                     обрабатывать многомерные и одномерные массивы, строки, символы, структуры и массивы структур.

·                     динамически создавать новые переменные в процессе выполнения программы.

·                     обрабатывать связанные структуры: стеки, очереди, списки, деревья, сети.

·                     передавать функциям адреса фактических параметров.

·                     передавать функциям адреса функция в качестве параметров.

Применение указателей часто критикуется из-за того, что в силу их природы невозможно определить, на что (на какую переменную) указывает в данный момент указатель, если не возвращаться к тому месту, где указателю в последний раз было присвоено значение. Это усложняет программу и делает её правильность сомнительной.

Программист, знающий Си, должен прежде всего знать, что такое указатели, и уметь их использовать.

Указатель-это переменная или константа, которая содержит значение адреса другой переменной.

 

 Рисунок1. Графическая интерпретация указателя

 

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

 

2.Объявление указателей и основные операции над ними

Указатель-это переменная или константа стандартного типа данных для хранения адреса переменной определённого типа. Тип адресуемой переменной может быть стандартный, перечислимый, структурный, объединение или void. Указатель на тип void может адрес.

Форма объявления переменной типа указатель:

тип [модификатор] *<имя-указателя>

где :

тип-имя типа переменной, адрес которой будет содержать переменная- указатель.(например integer, char, long)

имя-указателя –идентификатор переменной типа указатель.(имя собственное)

*- определяет переменную типа указатель.

Значение переменной-указателя-это адрес некоторой величины, целое без знака. При выводе значения указателя надо использовать формат %u. Указатель содержит адрес первого байта переменной определённого типа. Тип адресуемой переменной, на которую ссылается указатель, определяет объём оперативной памяти, выделяемой переменной, связанной с указателем. Для того, что бы машинной программой обработать (например прочитать или записать) значение переменной с помощью указателя, надо знать адрес её начального (нулевого) байта и количество байтов, которая занимает эта переменная. Ну и указатель естественно содержит эти данные:

Сам указатель содержит адрес нулевого байта этой переменной, а тип адресуемой переменной определяет, сколько байтов, начиная с нулевого (адреса, определённого указателем) занимает это значение.

Примеры объявлений даны на РИС.2

Рисунок2. Примеры объявлений указателей

Язык Си даёт возможность использования адресов переменных программы с помощью основных операций: & и *

&-получение адреса переменной.

*-извлечение значения, расположенного по этому адресу.

С помощью основных операций можно получить значение адреса переменной и использовать косвенную адресацию-получение значения переменной по её адресу.

Операции * и & можно писать вплотную к имени операнда или через пробел.Например: &i, *ptri.

Назначение этих операций:

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

*-имя указателя-получение значения определённого типа по заданному адресу. Определяет содержимое, находящееся по адресу, который содержится в указателе-переменной или указателе-константе. Иначе: косвенная адресация. Косвенная адресация значения с помощью операции * осуществляет доступ к значению по указателю, то есть извлечение значения, расположенного по адресу-содержимому указателя. Операнд *(т.е имя после этого значка) должно быть типа указатель(где-то раньше объявлено).

Оператор присваивания значения адреса указателю(иначе инициализация указателя) имеет вид:

имя указателя_переменной=&имя_переменной

Например: int *ptri,i; //объявление указателя и переменной типа int

ptri=&i; //ptri получает значение адреса ‘i’

В общем виде оператор присваивания, использующий имя указателя и * операцию косвеной адресации, можно представить в виде:

Имя_переменной=*имя_указателя

Где имя-указателя –это переменная или константа, которая содержит адрес размещаемого значения, требуемого для переменной левой части оператора присваивания.

Например: i=*ptri; // ‘i’ получает значение,расположенное по адресу

// содержащемся в указателе‘ptri’

Как и любые переменные, переменная типа указатель ptri имеет адрес и значение.

Схематично взаимосвязь между указателям и адресуемым значением представлениа на рис.3

 

Рисунок 3.Взаимосвязь указателя, адреса и значения переменной

Указатели можно использовать:

*ptri-значение переменной, находящейся по адресу, содержащемуся в указателяе ptri

ptri-значение адреса переменной

&ptri-адрес местоположения самого указателя

 

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

int i=123, j, *ptri; //объявление переменных и указателя

ptri=&i; //инициализация указателя(присвоение адреса i)

j=*ptri+1; //переменной i (*ptri) присваивается значение //переменной i и к её содержимому прибавляется единичка.

Следует отметить, что операции & и * более приоритетны, чем арифметические операции

3.Многоуровневая адресация

В языке Си можно использовать многоуровневую косвеную адресация, то есть косвеную адресация 1,2 и т.д. уровней. При этом для объявления и обращения к значениям с помощью указателей можно использовать соответственно несколко символов звёздочка *.Звёздочки при объявлении как бы уточняют назначение имени переменной, определяя уровень косвеной адресации для обращения к значениям с помощью этих указателей.Пример объявления переменной и указателей для многоуровневой косвеной адресации значений дан ниже:

int i=123; //где i-имя переменной

int *pi=&i; //pi –указатель на переменную

int **ppi=&pi; //ppi-указатель на ‘указатель на переменную’

int ***pppi=&ppi; //pppi-указатель на ‘указатель на ‘указатель на переменную’’.

Для обращения к значениям с помощью указателей можно применять следующее правило, жёстко связывающее форму обращения с объявлением этих указателей:

·                     Полное количество звёздочек косвеной адресации, равное количеству звёздочек при объявлении указателя, определяет значение переменной.

·                     Уменьшение количества звёздочек косвенной адресации добавляет к имени переменной слово

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

Пример, поясняющий это правило дан на РИС.4

Рисунок 4.Соответствие между количеством уточнений (*) и результатом обращения к значению с помощью указателя.

Где У.К.А.-уровень косвеной адресации

 

Пример, иллюстрирующий многоуровневую косвенную адресацию

 

4.Операции над указателями

Язык Си предоставляет возможности для выполнениянад указателями операций присваивания, целочисленой арифметики и сравнений.

На языке Си можно:

·                     Присвоить указателю значение адреса данных, или нуль.

·                     Увеличить (уменьшить) значение указателя

·                     Прибавить (вычесть) из значения указателя целое число

·                     Сложить или вычесть значение одного указателя из другово

·                     Сравнить два указателя с помощью операций отношения.

Переменной-указателю можно задать значение с помощью одного из способов:

·                     Присвоить указателю адрес переменной, имеющей место в оперетивной памяти, или нуль, например

: ptri=&i; ptri=NULL;

·                     Объявить указатель вне функции (в том числе

main) либо в любой функции, снабдив его описателем stastic, при этом начальным значением указателя является нулевой адрес (NULL)

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

, например: ptri=ptrj; -это двойное указание одной и той же переменной.

·                     Присвоить переменной-указателю значение с помощью функций

malloc и calloc.

Изменение значений указателя можно производить с помощью операций +, ++, -, --. Бинарные операции (+ и -) можно выполнять над указателями, если оба указателя ссылаются на переменные одного типа, так как объём оперативной памяти для различных типов данных может быть разный. Например, значение типа char занимает 1(один) байт, значение типа int занимает 2(два) байта, а под значение типа float выделяется аж 4(четыре) байта. Добавление 1 к указателю добавит ‘квант памяти’ ,то есть количество байтов, которое занимает одно значение адресуемого типа. Для указателя на элементы массива это означает, что осуществляется переход к адресу следующего элемента массива, а не следующего байта. То есть значение указателя при переходе от элемента к элементу массива целых чисел будет увеличиваться на 2, а типа float-на 4.Более подробно это продемонстрированно на РИС.5

 

Рисунок 5.Арифметические действия над различными типам указателей.

В языке Си++ связь между указателями и массивами настолько тесная, что программисты обычно предпочитают использовать указатели при работе с массивами. Поскольку массивы являются некоторым аналогом указателей, язык Си позволяет программам разыминовывать имена массивов с помощью такого выражения как *имя_массива, например:

int mas[10],*ptrm;

ptrm=&mas[0];

*prtm==mas[0]==*(mas+0) ; -значение нулевого элемента массива mas

*(ptrm+i)==mas[i]==*(mas+i); --значение i-го элемента массива mas

А операции над элементами массива mas можно представить в виде:

*mas+2==mas[0]+2; *(mas+i)-3==mas[i]-3;

А вот задачка, предложенная на собеседовании в одной софтверной фирме:

*(&(mas[i+1])+2)++;

·                     ptrm==&mas[i+1]; упрощаем данное выражение, i здесь не играет роли

·                     ptrm+2==&(mas[i+1])+2;

здесь указатель переводится на 2 элемента вперёд

·                     *ptrm++==(*ptrm=*ptrm+1); здесь содержимое ячейки массива извлекается и к нему прибавляется единичка

Если указатель имеет префиксные (слева от имени указателя) и постфиксные (справа от имени указателя) операции, то они выполняются в следующей последовательности:

·                     Префиксные операции в последовательности спарава налево.

·                     Использование значения, полученного после выполнения префиксных операций

·                     Постфиксная операция над указателем.

Например в выражении *p++ сначала выполняется префиксная операция над указателем ,то есть определяется значение *p-содержимое, расположенное по адресу px, а затем выполняется посфиксная операция ++ увелечение значения указателя на квант памяти, то есть на 2 байта (если указатель типа int)

А, например в выражениии (++(*p)+2) сначала:

·                     *p -так как префиксные операции выполняются справа налево.

·                     *p=*p+1

-самая ‘левая’ префиксная операция

·                     +2 -выполнение посфиксной операции

 

5.Проблеммы, связанные с указателями

Проблеммы, связанные с указателями, возникают при некорректном использовании этих указателей. Некорректным использованием указателей может быть:

·                     Попытка работать с неинициализированными указателям, то есть с указателем, не содержащим адреса оперативной памяти (ОП)

, выделеной переменной.

·                     Потеря ссылки, то есть значения указателя из-за присваивания ему нового значения до освобождения ОП, которою он адресует.

·                     Неосвобождение ОП, запрошенной с помощью функции

malloc

Попытка возвратить в качестве результата работы функции адрес локальной переменной (класса auto).

 

Создание и уничтожение динамических многомерных массивов

Как правило, работа с такими массивами осуществляется следующим образом:

const unsigned int DIM1 = 3;
const unsigned int DIM2 = 5;
 
int main() {
 
    int **ary;    // (1)
 
    // создание
    ary = new int * [DIM1];    // массив указателей (2)
    for (int i = 0; i < DIM1; i++) {   // (3)
        ary[i] = new int [DIM2];     // инициализация указателей
    }
 
    // работа с массивом
    for (int i = 0; i < DIM1; i++) {
        for (int j = 0; j < DIM2; j++) {
            ary[i][j] = (i + 1) * 10 + (j + 1);
        }
    }
 
    for (int i = 0; i < DIM1; i++) {
        for (int j = 0; j < DIM2; j++) {
            cout << setw(4) << ary[i][j];
        }
        cout << endl;
    }
 
    // уничтожение
    for (int i = 0; i < DIM1; i++) {
        delete [] ary[i];
    }
    delete [] ary;
 
    return 0;
}

(1) Для доступа к двумерному массиву объявляется переменная ary типа указатель на указатель на тип (в данном случае это указатель на указатель на int).

(2) Переменная инициализируется оператором new, который выделяет память для массива указателей на int.

(3) В цикле каждый элемент массива указателей инициализируется оператором new, который выделяет память для массива типа int.

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

Работа с динамическим многомерным массивом синтаксически полностью совпадает с работой с многомерным C-массивом.

Пример кода для трёхмерного массива:

const unsigned int DIM1 = 3;
const unsigned int DIM2 = 5;
const unsigned int DIM3 = 2;
 
int main() {
 
    int ***ary;
 
    int cnt = 1;
 
    // создание
    ary = new int ** [DIM1];
    for (int i = 0; i < DIM1; i++) {
        ary[i] = new int * [DIM2];
        for (int j = 0; j < DIM2; j++) {
            ary[i][j] = new int [DIM3];
        }
    }
 
    // работа с массивом
    for (int i = 0; i < DIM1; i++) {
        for (int j = 0; j < DIM2; j++) {
            for (int k = 0; k < DIM3; k++) {
                ary[i][j][k] = cnt++;
                cout << setw(4) << ary[i][j][k];
            }
            cout << endl;
        }
        cout << endl;
    }
 
    // уничтожение
    for (int i = 0; i < DIM1; i++) {
        for (int j = 0; j < DIM2; j++) {
            delete [] ary[i][j];
        }
        delete [] ary[i];
    }
    delete [] ary;
 
    return 0;
}

Где собака порылась

Работа с динамическим многомерным массивом синтаксически полностью совпадает с работой с многомерным C-массивом. (Цитирую предыдущий раздел.) Синтаксически — да, но между этими массивами есть глубокое различие, о котором начинающие программисты часто забывают.

Во-первых, для динамического массива выделяется другой объём памяти.

Если посчитать, сколько памяти будет выделяться для двумерного массива из примера выше, то получится: первый оператор new выделил память для 3 указателей, второй оператор new в цикле трижды выделил память для 5 элементов типа int. Т.е. получилось, что выделили памяти для 15 значений типа int и для 3 значений типа указатель на int. Для C-массива компилятором была выделена память только для 15 значений типа int. (Всяческие выравнивания и прочие оптимизации не учитываем!)

Во-вторых, память, выделенная для динамического массива, не непрерывна. Следовательно, хак №1 (обращение с двумерным массивом как с одномерным) работать не будет.

В-третьих, передача многомерных массивов в функции и работа с ними будет отличаться для динамических массивов и C-массивов.

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

Динамический многомерный массив НЕ является C-массивом.

Парадоксально, но факт, что наиболее близким родственничком для этих неродных близнецов, является хак №2, реализующий работу с многомерным массивом посредством одномерного массива (см. раздел Хаки). Все три вышеперечисленных различия для него неактуальны.

Стоит отметить, что массив указателей на массивы — структура более гибкая, чем двумерный C-массив. Например, для массива указателей на массивы размеры массивов могут быть разными, или какой-то массив может вообще отсутствовать. Наиболее распространённым примером является «массив строк», т.е. массив указателей на массивы типа char (пример — см. в следующем разделе).

 

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

1.     Для чего предназначены типы данных?

2.     Назовите классификацию типов данных?

3.     Какую размерность имеют целочисленные типы?

4.     Какую размерность имеют вещественные  типы?

Литература.

7.     Шилдт Г. С++: базовый курс, 3-е издание.: Пер. с англ.-М. : Издательский дом "Вильямс", 2010

8.     Архангельский А. Я. "Програмирование в C++ Builder". - М.: "Издательство Бином", 2003

9.     Деннис Ритчи "Язык программирования C. 2-е издание, переработанное и дополненное" Пер. с англ.-М. : Издательский дом "Вильямс", 2009

10. Керниган Б. "Язык программирования Си"-Питер. Невский Диалект, 2009

11. Вильямс А. Системное программирование в Windows 2000 для профессионалов - СПб: Питер, 2003. - 624 с.: ил.

12. Юркин А. Задачник по программированию. — СПб.: Питер, 2002. — 192 с.

 

Просмотрено: 0%
Просмотрено: 0%
Скачать материал
Скачать материал "Лекции по дисциплине "ОСНОВЫ АЛГОРИТМИЗАЦИИ И ПРОГРАММИРОВАНИЯ ""

Получите профессию

Бухгалтер

за 6 месяцев

Пройти курс

Рабочие листы
к вашим урокам

Скачать

Выбранный для просмотра документ Лекция 8 Определение функции.doc

ТЕМА Определение функции. Рекурсивные определения функций. Передача значений через глобальные переменные. Формальные параметры. Функции с переменным количеством параметров.

ТИП: комбинированное занятие.

ЦЕЛИ :

Учебная :

·        изучить способы описания процедур и функций.

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

Развивая :

·        • развивать логическое мышление , внимание , память ;

·        • развивать кругозор .

Воспитательная :

·        • развивать познавательный интерес к предмету.

·       Структура занятия

·       1 . Организационный момент ( 3 мин )

·       2 . Сообщения темы , цели занятия ( 5 мин )

·       3 . Актуализация знаний ( 10 мин )

·       4 . Выдача теоретического материала ( 20 мин )

·       5 . Проверка полученных знаний на практике ( 35 мин )

·       6 . Подведение итогов , выставление оценок ( 5 мин )

·       7 . Выдача домашнего задания ( 2 мин )

Литература.

1.     Шилдт Г. С++: базовый курс, 3-е издание.: Пер. с англ.-М. : Издательский дом "Вильямс", 2010

2.     Архангельский А. Я. "Програмирование в C++ Builder". - М.: "Издательство Бином", 2003

3.     Деннис Ритчи "Язык программирования C. 2-е издание, переработанное и дополненное" Пер. с англ.-М. : Издательский дом "Вильямс", 2009

4.     Керниган Б. "Язык программирования Си"-Питер. Невский Диалект, 2009

5.     Вильямс А. Системное программирование в Windows 2000 для профессионалов - СПб: Питер, 2003. - 624 с.: ил.

6.     Юркин А. Задачник по программированию. — СПб.: Питер, 2002. — 192 с.

Вопрос актуализации знаний:

1.     Приведите основные алгоритмы программирования?

2.     На какие блоки можно разбить программу?

3.     Как описываются переменные?

4.     Определение массива

 

 

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

1.     Назовите основные отличия в описании процедур и функций.

2.     Каким образом производится вызов функции в программе?

3.     Что лучше процедура или функция?

4.      Описание функции. Для чего объявляется прототип?

5.     Что такое формальные и фактические параметры? Локальные и глобальные?

6.     . Как можно передавать массив в функцию?

7.     . Способы вызова функций. 

План.

1.     Описание функций

2.     Передача информации в функцию

3.   Функции могут возвращать результат вызвавшей функции

4.     Функции, которые не возвращают значение

5.    Использование возвращаемого функцией значения

6.    Представление о прототипах функций

 

Описание функций

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

Как в случае с именами переменных, имена функций, которые вы выбираете те, должны соответствовать операции, выполняемой функцией. Например глядя на имена функций, перечисленные в табл. 9, вы получите хорошее представление о назначении каждой функции.

Таблица . Примеры смысловых имен функций.

Имя функции

Назначение функции

Print_test_scores

Печатать тестовые очки класса

Accounts_payable

Обработать счета компании

Get_user_name

Запрос имени пользователя

Print_document

Напечатать указанный документ

Calculate_income_tax

Определить подоходный налог пользователя

Функция C++ по структуре подобна программе main, которую вы использовали во всех предыдущих программах. Другими словами, имя функции предваряется ее типом, а за ним следует список параметров, описание которых появляется в скобках. Вы группируете операторы функций внутри левой и правой фигурных скобок, как показано ниже:

тип_возврата имя_функции (список_параметров)

{

объявления_переменных; 
операторы; 

}

Рассмотрите, например, как структура этой функции соответствует следующей программе main:

void main (void) //-----------> тип имя (список_параметров)


   int count; // ---------------------------> 
объявления_переменных
   for (count = 0; count < 10; count++) cout << count << " "; // -----> 
Оператор 
}

Следующие операторы определяют функцию с именем show_message, которая выводит сообщение на экран, используя cout.

void show_message (void)


   cout << "Привет, учусь программировать на C++" << endl; 
}

Как вы, возможно, помните из урока 2, слово void, предшествующее имени функции, указывает функции не возвращать значение. Подобно этому, слово void, содержащееся внутри круглых скобок, указывает (компилятору C++ и программистам, читающим ваш код), что функция не использует параметры (информацию, которую программа передает функции). Следующая программа SHOW_ MSG.CPP использует функцию show_message для вывода сообщения на экран:

#include <iostream.h>

void show_message (void)


   cout << "Привет, учусь программировать на C++" << endl; 
}

void main (void)


   cout << "Перед вызовом функции" << endl; 
   show_message (); 
   cout << "Вернулись из функции" << endl; 
}

Вы уже знаете, что выполнение программы всегда начинается внутри main. Внутри mainследующий оператор (вызов функции) вызывает функцию show_message:

show_message ();

Круглые скобки после имени функции сообщают компилятору C++, что ваша программа использует функцию. Позже вы узнаете, что внутри этих скобок программа может передавать в функции информацию (параметры). Если вы откомпилируете и запустите эту программу, на вашем экране появится следующий вывод:

С: >SHOW_MSG <ENTER>

Перед вызовом функции

Привет, учусь программировать на C++

Вернулись из функции

Если программа встречает вызов функции, она начинает выполнять операторы, находящиеся внутри функции. После того как программа выполнит все операторы, которые содержит функция (другими словами, функция завершится); выполнение программы продолжается с оператора, следующего непосредственно за вызовом функции:

#include <iostream.h>

void show_message (void)


   cout << "Привет, учусь программировать на C++" << endl; 
}

void main (void)


   cout << "Перед вызовом функции" << endl; 
   show_message (); 
   cout << "Вернулись из функции" << endl; 
}

В данном случае программа выполняет первый оператор в main, которой выводит сообщение для пользователя, что программа собирается вызвать функцию. Далее программа встречает вызов функции и запускает выполнение операторов в show_messsage. После того как программа выполнит единственный оператор функции, она возвращается обратно в mainи продолжает свое выполнение с оператора, непосредственно следующего за вызовом функции. В этом случае программа выводит сообщение, извещая пользователя о том, что она возвратилась из функции, и после этого заканчивает свою работу. Следующая программа TWO__MSGS.CPP использует две функции - show_title и show_lesson для вывода информации об этой книге:

#include <iostream.h>

void show_title (void)


   cout << "Книга: Учимся программировать на C++" << endl; 
}

void show_lesson (void) 

   cout << "Урок: Знакомство с функциями" << endl; 
}

void main (void) 

   show_title (); 
   show_lesson (); 
}

Когда программа начинает выполнение, она сначала вызывает функцию show_title, которая выводит сообщение с помощью cout. После завершения show_title программа вызывает функцию show_lesson, также выводящую сообщение. После завершения show_lessonпрограмма завершается, поскольку в main больше нет операторов.

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

Вызов функции

Функция Представляет собой набор связанных операторов, которые Выполняют определенную задачу. Создавая функции внутри программы, вы можете делить большие задачи на небольшие легко управляемые части. 
Ваши программы выполняют операторы функций посредством вызова функции. Для вызова функции программы просто обращаются к имени функции, за которым следуют круглые скобки, как показано ниже:

function_name();

Если программа передает информацию (параметры) в функцию, она размещает эту информацию внутри круглых скобок, разделяя ее запятыми:

payroll(employee_name, employee_id, salary);

После того как последний оператор функции завершен, выполнение программы продолжается с первого оператора следующего за вызовом функции.

Передача информации в функцию

Для увеличения потенциальных возможностей ваших функций C++ позволяет программам передавать информацию (параметры) в функции. Если функция использует параметры, вы должны сообщить C++ тип каждого параметра, например int, float, char и т.д. Следующая функция show_number использует параметр типа int.

void show_number (int value)


   cout << "Значение параметра равно " << value << endl; 
}

Если ваша программа вызывает функцию show_number, она должна передать ей значение, как показано ниже:

show_number ( 1001 //----------------> Значение, передаваемое в функцию

C++ будет подставлять переданное число вместо каждого имени параметра value внутри функции:

show_number (1001)

void show_number (int value )


   cout << "Значение параметра равно " << value << endl; 
}

void show_number (1001)


   cout << "Значение параметра равно " << 1001 << endl; 
}

Как видите, поскольку C++ замещает значение параметра, функция show_number выводит число 1001, переданное ей главной программой.

Следующая программа USEPARAM.CPP использует функцию show_number несколько раз, каждый раз передавая разные числа:

#include <iostream.h>

void show_number (int value)


   cout << "Значение параметра равно " << value << endl; 
}

void main (void)


   show_number (1); 
   show_number (1001); 
   show_number (-532); 
}

Если вы откомпилируете и запустите эту программу, на вашем экране будет отображено следующее:

С: >USEPARAM <ENTER>

Значение параметра равно 1

Значение параметра равно 1001

Значение параметра равно -532

Как видите, каждый раз, когда программа вызывает функцию, C++ присваивает передаваемое число переменной value. Найдите время для эксперимента с этой программой, изменяя значения, которые main передает в функцию, и обращая внимание на результат.

Каждый параметр функции имеет определенный тип. В случае функции show_numberпараметр value должен быть типа int. Если вы попытаетесь передать в функцию значение другого типа, например с плавающей точкой, компилятор будет сообщать об ошибке. В большинстве случаев ваши программы будут передавать несколько значений в функцию. Для каждого передаваемого параметра функция должна указать имя и тип. Например, следующая программа BIGSMALL.CPP использует функцию show_big_and_little для вывода самого большого и самого маленького из трех полученных целочисленных значений:

#include <iostream.h>

void show_big_and_little (int a, int b, int c)


   int small = a; 
   int bbr>ig = a;

   if (b > big) 
      big = b;

   if (b < small) 
      small = b;

   if (c > big) 
      big = c;

   if (c < small) 
      small = c;

   cout << "Самое большое значение равно " << big << endl; 
   cout << "Самое маленькое значение равно " << small << endl; 
}

void main (void)


   show_big_and_little (1, 2, 3); 
   show_big_and_little (500, 0, -500); 
   show_big_and_little (1001, 1001, 1001); 
}

Если вы откомпилируете и запустите эту программу, на вашем экране появится следующий вывод:

С: > BIGSMALL <ENTER>

Самое большое значение равно 3

Самое маленькое значение равно 1

Самое большое значение равно 500

Самое маленькое значение равно -500

Самое большое значение равно 1001

Самое маленькое значение равно 1001

Наконец, следующая программа SHOW_EMP.CPP использует функцию show_employee для вывода возраста (тип int) и оклада (тип float) служащего:

#Include <iostream.h>

void show_employee (int age, float salary)


   cout << "Возраст служащего " << age << " года (лет)" << endl; 
   cout << "Служащий получает $" << salary << endl; 
}

void main (void)


   show_employee (32, 25000.00); 
}

Как видите, функция show_employee определяет параметры типа int и float

Функции могут возвращать результат вызвавшей функции

Функция должна выполнять определенную задачу для вашей программы. В большинстве случаев функции будут выполнять некоторые типы вычислений. Затем функция возвратит свой результат вызвавшей функции. Когда функция возвращает значение, вы должны сообщить C++ тип значения, например int, float, char т. д. Чтобы информировать C++ о типе возвращаемого функцией значения, просто поставьте перед именем функции соответствующий тип. Например, следующая функция add_values складывает два своих целочисленных параметра и возвращает результат типа int вызвавшей программе:

int add_values (int а, int b)


   int result; 
   result= 
а+b; 
   return (result); 
}

В данном случае слово int, появляющееся перед именем функции, указывает тип возвращаемого значения функции. Функции используют оператор return для возврата значения вызвавшей функции. Когда ваша программа встречает оператор return, она возвращает заданное значение и завершает выполнение функции, возвращая управление вызвавшей программе. В программе вы можете использовать возвращаемое значение, как показано ниже:

result=add_values (1, 2);

В данном случае программа присваивает возвращаемое функцией значение переменнойresult. Ваша программа может также сразу же напечатать возвращаемое функцией значение с помощью cout, как показано ниже:

cout << "Сумма значений равна " << add_values (500, 501) << endl;

Предыдущая реализация функции add_values использовала три оператора, чтобы было легче понять смысл функции. Однако вы можете сократить функцию до единственного оператораreturn, как показано ниже:

int add_values (int a, int b)


   return (a+ b); 
}

Следующая программа ADDVALUE.CPP использует функцию add_values для сложения нескольких значений:

#include <iostream.h>

int add_values (int a, int b)


   return (a+ b); 
}

void main (void)


   cout << " 100 + 200 = " << add_values(100, 200) << endl; 
   cout << " 500 + 501 = " << add_values(500, 501) << endl 
   cout << "-1 + 1 = " << add_values(-1, 1) << endl; 
}

Выберите время для эксперимента с этой программой, изменяя значения, которые программа передает в функцию. Вы могли бы попытаться передать в функцию большие значения, например 20000 и 30000. Как и можно предложить, выполнение функции, возвращающей значение типа int, приведет к ошибке переполнения.

Не все функции возвращают значение типа int. Следующая функция average_ valueвозвращает среднее двух целочисленных значений, которое может быть дробным, например 3.5:

float average_value(int a, int b)


   return( (a + b) / 2.0); 
}

В этом случае слово float, которое предшествует имени функции, указывает тип возвращаемого функцией значения.

Функции, которые не возвращают значение

Если функция не возвращает значение, вам необходимо предварить имя функции типом void.В противном случае вы должны предварять имя функции типом возвращаемого функцией значения, например, int, float, char и т. д. Чтобы возвратить значение вызвавшей функции, функция использует оператор return. Когда ваша программа встречает оператор return,выполнение функции завершается и указанное значение возвращается вызвавшей функции. Возможны ситуации, когда вы встретите оператор return в функции, которая не возвращает значение:

return;

В этом случае функция имеет тип void (не возвращает значение) и оператор return просто завершает выполнение функции.

Замечание: Если операторы появляются в функции после оператора return они не будут выполняться. Как уже обсуждалось выше, если ваша программа встречает оператор return в функции, то возвращается соответствующее значение, функция заканчивается и выполнение программы продолжается с первого оператора, следующего за вызовом функции.

Использование возвращаемого функцией значения

Когда функция возвращает значение, вызвавшая программа может присвоить возвращенное значение переменной, используя оператор присваивания, как показано ниже:

payroll_amount = payroll (employee, hours, salary);

В дополнение к этому вызвавшая программа просто может обращаться к функции. Например, следующий оператор выводит возвращаемое функцией значение, используя cout.

cout << "Служащий получил" << payroll(employee, hours, salary) < < endl;

Вызвавшая функция может также использовать возвращаемое значение в условии, как показано ниже:

if (payroll(employee, hours, salary) < 500.00) 
cout << "Этот служащий нуждается в повышении" << endl;

Как видите, программа может использовать возвращаемое функцией значение различными способами.

Представление о прототипах функций

Прежде чем ваша программа сможет вызвать функцию, C++ должен знать тип воозвращаемого значения, а также количество и тип параметров, используемых функцией. В каждой из программ, представленных в этом уроке, определение функции, вызываемой программой, всегда предшествует вызову функции в исходном файле. Однако в большинстве случаев функции появляются в вашем исходном файле и, как правило, одна функция вызывает другую. Чтобы гарантировать, что C++ знает особенности каждой функции, используемой в программе, вы можете поместить прототипы функций в начало исходного файла. В общем случае прототип функции обеспечивает информацию о типе возвращаемого функцией значения и ее параметрах. Следующий оператор иллюстрирует прототипы функций для нескольких функций, используемых в данном уроке:

void show_message(void);

void show_number(int);

void show_employee(int, float);

int add_values(int, int);

float average_value(int, int);

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

float average_value ( int, int) ;

Если ваша программа вызывает функцию, для которой компилятор C++ не нашел определения или прототипа, компилятор сообщает о синтаксической ошибке. При исследовании заголовочных файлов C++ или других программ вы будете постоянно сталкиваться с прототипами функций. Следующая программа PROTO.CPP иллюстрирует использование прототипа Функции:

#include <iostream.h>

float average_value(int, int); // Прототип функции

void main(void)


    cout << "Среднее значение 2000 и 2 равно " << average_value(2000, 2) << endl; 
}

float average_value (int a, int b)


   return((a + b) / 2.0); 
}

В этом случае программа вызывает функцию average_value до того, как функция определена. Таким образом, программа использует прототип функции, который предваряет определениеmain. Если вы удалите прототип функции и откомпилируете эту программу, компилятор C++ будет сообщать о синтаксических ошибках.

 

 

Просмотрено: 0%
Просмотрено: 0%
Скачать материал
Скачать материал "Лекции по дисциплине "ОСНОВЫ АЛГОРИТМИЗАЦИИ И ПРОГРАММИРОВАНИЯ ""

Получите профессию

Методист-разработчик онлайн-курсов

за 6 месяцев

Пройти курс

Рабочие листы
к вашим урокам

Скачать

Выбранный для просмотра документ Лекция 9 Общая характеристика языков ассемблера. Работа с файлами. Использование ассемблерных вставок.doc

ТЕМА Общая характеристика языков ассемблера. Работа с файлами.  Использование ассемблерных вставок.

ТИП: комбинированное занятие.

ЦЕЛИ :

Учебная :

·        изучить основные функции для работы с файлами.

·        научиться использовать функциями для работы с файлами

Развивая :

·        • развивать логическое мышление , внимание , память ;

·        • развивать кругозор .

Воспитательная :

·        • развивать познавательный интерес к предмету.

·       Структура занятия

·       1 . Организационный момент ( 3 мин )

·       2 . Сообщения темы , цели занятия ( 5 мин )

·       3 . Актуализация знаний ( 10 мин )

·       4 . Выдача теоретического материала ( 20 мин )

·       5 . Проверка полученных знаний на практике ( 35 мин )

·       6 . Подведение итогов , выставление оценок ( 5 мин )

·       7 . Выдача домашнего задания ( 2 мин )

Литература.

1.     Шилдт Г. С++: базовый курс, 3-е издание.: Пер. с англ.-М. : Издательский дом "Вильямс", 2010

2.     Архангельский А. Я. "Програмирование в C++ Builder". - М.: "Издательство Бином", 2003

3.     Деннис Ритчи "Язык программирования C. 2-е издание, переработанное и дополненное" Пер. с англ.-М. : Издательский дом "Вильямс", 2009

4.     Керниган Б. "Язык программирования Си"-Питер. Невский Диалект, 2009

5.     Вильямс А. Системное программирование в Windows 2000 для профессионалов - СПб: Питер, 2003. - 624 с.: ил.

6.     Юркин А. Задачник по программированию. — СПб.: Питер, 2002. — 192 с

Вопрос актуализации знаний:

1.     Что такое файл?

2.     Дайте определение файловой системы?

3.     Дайте определение командной строки.

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

1.     Какие функции используются для работы с файлами

2.     Как подключается внешний файл?

3.     Как записать строку в файл?

4.     Функции для работы с командной стракой

5.     К каким последствиям может привести невозможность выполнить какую-либо файловую операцию. Возможно ли предусмотреть в программе такие ситуации?

6.     Каким образом можно определить достижение конца файла при чтении?

7.     Как определить имена файлов в каталоге?

 

План.

1.     Открытие файла:

2.     Закрытие файла:

3.     Работа с содержимым файла:

4.     Общие операции по работе с файлами:

 

Существуют два основных типа файлов: текстовые и двоичные. Файлы позволяют пользователю считывать большие объемы данных непосредственно с диска, не вводя их с клавиатуры.

 

1.     Текстовыми называются файлы, состоящие из любых символов. Они организуются по строкам, каждая из которых заканчивается символом «конец строки». Конец самого файла обозначается символом «конец файла». При записи информации в текстовый файл, просмотреть который можно с помощью любого текстового редактора, все данные преобразуются к символьному типу и хранятся в символьном виде.

 

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

 

Для работы с файлами используются специальные типы данных, называемые потоками. Поток ifstream служит для работы с файлами в режиме чтения, а ofstream в режиме записи. Для работы с файлами в режиме как  записи, так и чтения служит поток fstream.

 

В программах на C++ при работе с текстовыми файлами необходимо подключать библиотеки iostream и fstream.

Для того чтобы записывать данные в текстовый файл, необходимо:

1.     описать переменную типа ofstream.

2.     открыть файл с помощью функции open.

3.     вывести информацию в файл.

4.     обязательно закрыть файл.

Для считывания данных из текстового файла, необходимо:

1.     описать переменную типа ifstream.

2.     открыть файл с помощью функции open.

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

4.     закрыть файл.

Запись информации в текстовый файл

1.     Как было сказано ранее, для того чтобы начать работать с текстовым файлом, необходимо описать переменную типа ofstream. Например, так:

 

ofstream F;

 

2.     Будет создана переменная F для записи информации в файл.

3.     На следующим этапе файл необходимо открыть для записи. В общем случае оператор открытия потока будет иметь вид:

 

F.open(«file», mode);

 

Здесь F — переменная, описанная как ofstream,

         file — полное имя файла на диске,

        mode — режим работы с открываемым файлом.

!!!

Обратите внимание на то, что при указании полного имени файла нужно ставить двойной слеш. Например, полное имя файла noobs.txt, находящегося в папке game на диске D:, нужно будет записать так:

 

D:\\game\\noobs.txt.

 

Файл может быть открыт в одном из следующих режимов:

ios::in — открыть файл в режиме чтения данных, этот режим является режимом по умолчанию для потоков ifstream;

ios::out — открыть файл в режиме записи данных (при этом информация о существующем файле уничтожается), этот режим является режимом по умолчанию для потоков ofstream;

ios::app — открыть файл в режиме записи данных в конец файла;

ios::ate — передвинуться в конец уже открытого файла;

ios::trunc — очистить файл, это же происходит в режиме ios::out;

ios::nocreate — не выполнять операцию открытия файла, если он не существует;

ios::noreplace — не открывать существующий файл.

 

!!!

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

 

После удачного открытия файла (в любом режиме) в переменной F будет храниться true, в противном случае false. Это позволит проверить корректность операции открытия файла.

 

Открыть файл (в качестве примера возьмем файл D:\\game\\noobs.txt) в режиме записи можно одним из следующих способов:

//первый способ

 ofstream F;

 F.open("D:\\game\\noobs.txt", ios::out);

//второй способ, режим ios::out является режимом по умолчанию

//для потока ofstream

 ofstream F;

 F.open("D:\\game\\noobs.txt");

//третий способ объединяет описание переменной и типа поток

//и открытие файла в одном операторе

 ofstream F ("D:\\game\\noobs.txt", ios::out);

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

Если вы хотите открыть существующий файл в режиме до записи, то в качестве режима следует использовать значение ios::app.

!!!

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

 

Например,  для записи в поток F переменной a, оператор вывода будет иметь вид:

 

F<<a;

 

Для последовательного вывода в поток G переменных b, c, d оператор вывода станет таким:

 

G<<b<<c<<d;

 

Закрытие потока осуществляется с помощью оператора:

 

F.close();

ПРИМЕР:

 

Создать текстовый файл D:\\game\\noobs.txt и записать в него n вещественных чисел.

#include "stdafx.h"

#include <iostream>

#include <fstream>

#include <iomanip>

using namespace std;

int main()

{

 setlocale (LC_ALL, "RUS");

int i, n;

double a;

//описывает поток для записи данных в файл

 ofstream f;

//открываем файл в режиме записи,

//режим ios::out устанавливается по умолчанию

 f.open("D:\\game\\noobs.txt", ios::out);

//вводим количество вещественных чисел

cout<<"n="; cin>>n;

//цикл для ввода вещественных чисел

//и записи их в файл

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

{

cout<<"a=";

//ввод числа

cin>>a;

 f<<a<<"\t";

}

//закрытие потока

 f.close();

system("pause");

return 0;

}

 

_______________________________________________________________

Для того чтобы прочитать информацию из текстового файла, необходимо описать переменную типа ifstream. После этого нужно открыть файл для чтения с помощью оператора open. Если переменную назвать F, то первые два оператора будут такими:

 

ifstream F;

F.open("D:\\game\\noobs.txt", ios::in);

!!!

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

 

Например, для чтения из потока F в переменную a, оператор ввода будет выглядеть так:

 

F>>a;

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

Здесь F - имя потока функция возвращает логическое значение: true или false, в зависимости от того достигнут ли конец файла. Следовательно, цикл для чтения содержимого всего файла можно записать так:

 

//организуем для чтения значений из файла, выполнение

//цикла прервется, когда достигнем конец файла,

//в этом случае F.eof() вернет истину

while (!F.eof())

{

//чтение очередного значения из потока F в переменную a

 F>>a;

//далее идет обработка значения переменной a

}

 

ПРИМЕР:

 

В текстовом файле D:\\game\\noobs.txt хранятся вещественные числа, вывести их на экран и вычислить их количество.

 

#include "stdafx.h"

#include <iostream>

#include <fstream>

#include <iomanip>

#include <stdlib.h>

using namespace std;

int main()

{

 setlocale (LC_ALL, "RUS");

int n=0;

float a;

 fstream F;

//открываем файл в режиме чтения

 F.open("D:\\game\\noobs.txt");

//если открытие файла прошло корректно, то

if (F)

{

//цикл для чтения значений из файла; выполнение цикла прервется,

//когда достигнем конца файла, в этом случае F.eof() вернет истину.

while (!F.eof())

{

//чтение очередного значения из потока F в переменную a

 F>>a;

//вывод значения переменной a на экран

cout<<a<<"\t";

//увеличение количества считанных чисел

 n++;

}

//закрытие потока

 F.close();

//вовод на экран количества считанных чисел

cout<<"n="<<n<<endl;

}

//если открытие файла прошло некорректно, то вывод

//сообщения об отсутствии такого файла

else cout<<" Файл не существует"<<endl;

system("pause");

return 0;

}

 

C++. Обработка двоичных файлов

 

При записи информации в двоичный файл символы и числа записываются в виде последовательности байт.

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

1.     описать файловую переменную типа FAIL * с помощью оператора FILE *filename;. Здесь filename — имя переменной, где будет храниться указатель на файл.

2.     открыть файл с помощью функции fopen

3.     записать информацию в файл с помощью функции fwrite

4.     закрыть файл с помощью функции fclose

 

Для того чтобы считать данные из двоичного файла, необходимо:

1.     описать переменную типа FILE *

2.     открыть файл с помощью функции fopen

3.     считать необходимую информацию из файла с помощью функции fread, при этом следить за тем достигнут ли конец файла.

4.     закрыть файл с помощью функции fclose

 

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

 

Для открытия файла предназначена функция fopen.

 

FILE *fopen(const *filename, const char *mode)

 

Здесь filename — строка, в которой хранится полное имя открываемого файла, mode - строка, определяющая режим работы с файлом; возможны следующие значения:

«rb» — открываем двоичный файл в режиме чтения;

«wb» — создаем двоичный файл для записи; если он существует, то его содержимое очищается;

«ab» — создаем или открываем двоичный файл для дозаписи в конец файла;

«rb+» — открываем существующий двоичный файл в режиме чтения и записи;

«wb+» — открываем двоичный файл в режиме чтения и записи, существующий файл очищается;

«ab+» — двоичный файл открывается или создается для исправления существующий информации и добавления новой в конец файла.

 

Функция возвращает в файловой переменной f значение NULL в случае неудачного открытия файла. После открытия файла доступен 0-й его байт, указатель файла равен 0, значение которого по мере чтения или записи смещается на считанное (записанное) количество байт. Текущие значение указателя файла — номер байта, начиная с которого будет происходить операция чтения или записи.

 

Для закрытия файла предназначена функция fclose

 

int fclose(FILE *filename);

 

Возвращает 0 при успешном закрытие файла и NULL в противном случае.

 

Функция remove предназначена для удаления файлов.

 

int remove(const char *filename);

 

Эта функция удаляет с диска файл с именем filenema. Удаляемый файл должен быть закрыт. Функция возвращает ненулевое значение, если файл не удалось удалить.

 

Для переименования файлов предназначена функция rename:

 

int rename(const char *oldfilename, const char *newfilename);

 

Первый параметр — старое имя файла, второй — новое. Возвращает 0 при удачном завершении программы.

 

Чтение из двоичного файла осуществляется с помощью функции fread:

 

fread(void *ptr, size, n, FILE *filename);

 

Функция fread считывает из файла filename в массив ptr n элементов размера size. Функция возвращает количество считанных элементов. После чтения из файла его указатель смещается на n*size байт.

 

Запись в двоичный файл осуществляется с помощью функции fwrite:

 

fwrite(const void *ptr, size, n, FILE *filename);

Функция fwrite записывает в файл filename из массива ptr n элементов размера size. Функция возвращает количество записанных элементов. После записи информации в файл указатель смещается на n*size байт.

 

Для контроля достижения конца файла есть функция  feof:

 

int feof(FILE *filename);

 

Она возвращает ненулевое значение если достигнут конец файла.

 

ПРИМЕР:

 

Создать двоичный файл D:\\game\\noobs.dat и записать в него целое число n и n вещественных чисел.

 

#include "stdafx.h"

#include <iostream>

using namespace std;

int main()

{

 setlocale (LC_ALL, "RUS");

int n, i;

double a;

FILE *f; //описываем файловую переменную

//создаем двоичный файл в режиме записи

 f=fopen("D:\\game\\noobs.dat", "wb");

//ввод числа n

cout<<"n="; cin>>n;

fwrite(&n, sizeof(int), 1, f);

//цикл для ввода n вещественных чисел

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

{

//ввод очередного вещественного числа

cout<<"a=";

cin>>a;

//запись вешественного числа в двоичный файл

fwrite(&a, sizeof(double), 1, f);

}

//закрываем файл

fclose(f);

system("pause");

return 0;

}

 

 

ПРИМЕР:

Вывести на экран содержимого созданного в прошлой задаче двоичного файла D:\\game\\noobs.dat

 

#include "stdafx.h"

#include <iostream>

using namespace std;

int main()

{

 setlocale (LC_ALL, "RUS");

int n, i;

double *a;

FILE *f; //описываем файловую переменную

//открываем существующий двоичный файл в режиме чтения

 f=fopen("D:\\game\\noobs.dat", "rb");

//считываем из файла одно целое число в переменную n

fread(&n, sizeof(int), 1, f);

//вывод n на экран

cout<<"n="<<n<<endl;

//выделение памяти для массива из n чисел

 a=new double[n];

//чтение n вещественных чисел из файла в массив a

fread(a, sizeof(double), n, f);

//вывод массива на экран

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

cout<<a[i]<<"\t";

cout<<endl;

//закрываем файл

fclose(f);

system("pause");

return 0;

}

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

int n, i;

double a;

FILE *f;

 f=fopen("D:\\game\\noobs.dat", "rb");

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

fread(&a, sizeof(double), 1, f);

fclose(f);

 f=fopen("D:\\game\\noobs.dat", "rb");

fread(&a, sizeof(double), 1, f);

fclose(f);

 

Как видно, такое чтение чисел из файла, а затем повторное открытие файла — не самый удобный способ. Гораздо удобнее будет использовать функцию fseek перемещения указателя файла к заданному байту.

 

int fseek(FILE *filename, long int offset, int origin);

 

Функция устанавливает указатель текущий позиции файла F в соответствии со значением начала отсчета origin и смещения offset. Параметр offset равен количеству байтов, на которые будет смещен указатель файла относительно начала отсчета, заданного параметром origin. В качестве значения для параметра origin должно быть взято одно из следующих значений отсчета смещения offset, определенных в заголовке stdio.h:

SEEK_SET — с начала файла;

SEEK_CUR — с текущей позиции;

SEEK_END — с конца файла.

 

Функция возвращает нулевое значение при успешном выполнение операции, ненулевое — при возникновении сбоя при выполнении смещения

 

Функция fseek фактически реализует прямой доступ к любому значению в файле. Необходимо только знать месторасположение (номер байта) значения в файле. Рассмотрим использование прямого доступа в двоичных файлах на примере решения следующей задачи.

 

ПРИМЕР

 

В созданном раннее двоичном файле D:\\game\\noobs.dat, поменять местами наибольшее и наименьшее из вещественных чисел.

 

Алгоритм решения задачи состоит из следующих этапов:

1.     чтение вещественных из файла в массив a.

2.     поиск в массиве а максимального (max) и минимального (min) значения и их номеров (imax, imin).

3.     перемещения указателя файла к максимальному значению и запись min.

4.     перемещения указателя файла к минимальному значению и запись max.

 

Ниже приведен текст программы решения задачи с комментариями.

#include "stdafx.h"

#include <iostream>

using namespace std;

int main()

{

 setlocale (LC_ALL, "RUS");

int n, i, imax, imin;

double *a, max, min;

FILE *f;

//открытие файла в режиме чтения и записи

 f=fopen("D:\\game\\noobs.dat", "rb+");

//считываем из файла в переменную n количество

//вещественных чисел в файле

fread(&n, sizeof(int), 1, f);

cout<<"n="<<n<<endl;

//выделяем память для хранения вещественных чисел,

//которые будут храниться в массиве a

 a=new double[n];

//считываем из файла в массив а вещественные числа

fread(a, sizeof(double), n, f);

//поиск максимального и минимального элементов

//в массиве а и их индексов

for (imax=imin=0, max=min=a[0], i=1; i<n; i++)

{

if (a[i]>max)

{

 max=a[i];

 imax=i;

}

if (a[i]<min)

{

 min=a[i];

 imin=i;

}

}

//перемещение указателя к максимальному элементу

fseek(f, sizeof(int)+imax*sizeof(double), SEEK_SET);

//запись min вместо максимального элемента файла

fwrite(&min, sizeof(double), 1, f);

//перемещение указателя к минимальному элементу

fseek(f, sizeof(int)+imin*sizeof(double), SEEK_SET);

//запись max вместо минимального элемента файла

fwrite(&max, sizeof(double), 1, f);

//закрытие файла

fclose(f);

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

delete [ ]a;

system("pause");

return 0;

}

 

Просмотрено: 0%
Просмотрено: 0%
Скачать материал
Скачать материал "Лекции по дисциплине "ОСНОВЫ АЛГОРИТМИЗАЦИИ И ПРОГРАММИРОВАНИЯ ""

Получите профессию

Бухгалтер

за 6 месяцев

Пройти курс

Рабочие листы
к вашим урокам

Скачать

Получите профессию

Интернет-маркетолог

за 6 месяцев

Пройти курс

Рабочие листы
к вашим урокам

Скачать

Скачать материал

Найдите материал к любому уроку, указав свой предмет (категорию), класс, учебник и тему:

6 666 325 материалов в базе

Скачать материал

Другие материалы

Вам будут интересны эти курсы:

Оставьте свой комментарий

Авторизуйтесь, чтобы задавать вопросы.

  • Скачать материал
    • 17.10.2018 14262
    • RAR 1.4 мбайт
    • 487 скачиваний
    • Рейтинг: 5 из 5
    • Оцените материал:
  • Настоящий материал опубликован пользователем Рогозин Вячеслав Сергеевич. Инфоурок является информационным посредником и предоставляет пользователям возможность размещать на сайте методические материалы. Всю ответственность за опубликованные материалы, содержащиеся в них сведения, а также за соблюдение авторских прав несут пользователи, загрузившие материал на сайт

    Если Вы считаете, что материал нарушает авторские права либо по каким-то другим причинам должен быть удален с сайта, Вы можете оставить жалобу на материал.

    Удалить материал
  • Автор материала

    Рогозин Вячеслав Сергеевич
    Рогозин Вячеслав Сергеевич
    • На сайте: 7 лет и 4 месяца
    • Подписчики: 1
    • Всего просмотров: 50499
    • Всего материалов: 13

Ваша скидка на курсы

40%
Скидка для нового слушателя. Войдите на сайт, чтобы применить скидку к любому курсу
Курсы со скидкой

Курс профессиональной переподготовки

Бухгалтер

Бухгалтер

500/1000 ч.

Подать заявку О курсе
  • Сейчас обучается 27 человек из 20 регионов

Курс профессиональной переподготовки

Управление сервисами информационных технологий

Менеджер по управлению сервисами ИТ

600 ч.

9840 руб. 5600 руб.
Подать заявку О курсе
  • Сейчас обучается 26 человек из 19 регионов
  • Этот курс уже прошли 34 человека

Курс профессиональной переподготовки

Информатика: теория и методика преподавания в профессиональном образовании

Преподаватель информатики

300/600 ч.

от 7900 руб. от 3650 руб.
Подать заявку О курсе
  • Сейчас обучается 49 человек из 22 регионов
  • Этот курс уже прошли 152 человека

Курс профессиональной переподготовки

Информационные технологии в профессиональной деятельности: теория и методика преподавания в образовательной организации

Преподаватель информационных технологий

300/600 ч.

от 7900 руб. от 3650 руб.
Подать заявку О курсе
  • Сейчас обучается 191 человек из 54 регионов
  • Этот курс уже прошли 974 человека

Мини-курс

Социальные и правовые аспекты эпохи Просвещения: влияние на образование сегодня

4 ч.

780 руб. 390 руб.
Подать заявку О курсе

Мини-курс

Современные технологии в образовании (робототехника)

10 ч.

1180 руб. 590 руб.
Подать заявку О курсе
  • Сейчас обучается 20 человек из 12 регионов

Мини-курс

Интеллектуальная собственность: медиа и фотографии

4 ч.

780 руб. 390 руб.
Подать заявку О курсе
  • Сейчас обучается 44 человека из 24 регионов