Вы находитесь на странице: 1из 154

С. Л.

Беляков
А. В. Боженюк
М. В. Петряева

Основы разработки
программ
на языке C++
для систем
информационной
безопасности
МИНИСТЕРСТВО НАУКИ И ВЫСШЕГО ОБРАЗОВАНИЯ
РОССИЙСКОЙ ФЕДЕРАЦИИ
Федеральное государственное автономное
образовательное учреждение высшего образования
«ЮЖНЫЙ ФЕДЕРАЛЬНЫЙ УНИВЕРСИТЕТ»

Инженерно-технологическая академия

С. Л. БЕЛЯКОВ
А. В. БОЖЕ II ІО К
М. В. ПЕТРЯЕВА

ОСНОВЫ РАЗРАБОТКИ ПРОГРАММ


НА ЯЗЫКЕ C++ ДЛЯ СИСТЕМ
ИНФОРМАЦИОННОЙ БЕЗОПАСНОСТИ

Учебное пособие

Ростов-на-Дону - Т аганрог
Издательство Южного федерального университета
2020
УДК 004.438:004.056 (075.8)
ББК 32.973-018.1я73
Б448

Печатается по решению кафедры информационно-аналитических


систем безопасности Института компьютерных технологий
и информационной безопасности Южного федерального университета
(протокол № 5 от 20 февраля 2020 г.)

Рецензенты:
доктор технических наук, профессор, заведующий кафедрой информатики
Таганрогского института имени А. П. Чехова (филиал) «Ростовского
государственного Экономического университета (РИНХ)» Я. Е. Ромм

кандидат технических наук, доцент кафедры систем автоматического


управления РСУ ЮФУ О. В. Косенко

Беляков, С. Л.
Б448 Основы разработки программ на языке C++ для систем информа­
ционной безопасности : учебное пособие / С. Л. Беляков, А. В. Боже-
нюк, М. В. Петряева ; Южный федеральный университет. - Ростов-на-
Дону ; Таганрог : Издательство Южного федерального университета,
2020. - 152 с.
ISBN 978-5-9275-3521-7
Изложены необходимые для освоения курса сведения - краткий кон­
спект лекций, методические указания к выполнению лабораторных работ, ин­
дивидуального задания, а также образцы тестовых вопросов. Направление
подготовки 120700 «Защита информации».

УДК 004.438:004.056 (075.8)


ББК 32.973-018.1я73
ISBN 978-5-9275-3521-7

© Южный федеральный университет, 2020


© Беляков С. Л., Боженюк А. В.,
Петряева М. В., 2020
© Оформление. Макет. Издательство.
Южного федерального университета, 2020

2
СОДЕРЖАНИЕ

ВВЕДЕНИЕ............................................................................................... 5
1. КАЧЕСТВО ПРОГРАМ М ................................................................. 7
1.1. Правильность программы........................................................... 7
1.2. Надёжность программы.............................................................. 9
1.3. Время получения результата..................................................... 10
1.4. Используемые ресурсы ................................................................. 10
1.5. Защ ита............................................................................................. 11
2. ОСНОВНЫЕ ЭТАПЫ РАЗРАБОТКИ ПРОГРАМ М ............... 13
3. АЛГОРИТМИЗАЦИЯ......................................................................... 17
4. ИСПОЛНЕНИЕ ПРОГРАМ М .......................................................... 22
5. СТРУКТУРА ПРОГРАММЫ НА C + + ......................................... 24
5.1. Поточный ввод-вывод в C + + ..................................................... 27
5.2. Вывод информации...................................................................... 28
5.3. Ввод информации.......................................................................... 28
5.4. Ввод символьных строк................................................................ 28
5.5. Манипуляторы потока.................................................................. 28
6. ПЕРЕМЕННЫЕ ПРОГРАММЫ И ОБЛАСТИ ИХ ДЕЙСТВИЯ 32
7. ТИПЫ ДАННЫ Х............................................................................... 34
7.1. Символьный т и п ........................................................................... 35
7.2. Числовые т и п ы .............................................................................. 37
7.3. Преобразование типов данных в С + + ....................................... 41
7.4. Неявное преобразование т и п а ..................................................... 41
7.5. Числовое расширение.................................................................. 42
7.6. Числовая конверсия...................................................................... 42
7.7. Обработка арифметических выражений................................... 42
7.8. Приоритет типов операндов........................................................ 43
7.9. Явное преобразование типов данны х........................................ 43
8. ПОРАЗРЯДНАЯ ОБРАБОТКА ДАННЫ Х................................... 46
8.1. Шифрование м атриц..................................................................... 48
8.2. Шифр В ернама.............................................................................. 49

3
Содержание

9. УКАЗАТЕЛИ....................................................................................... 50
10. СИМВОЛЬНЫЕ МАССИВЫ И СТРО КИ................................ 53
11. ПЕРЕДАЧА ПАРАМЕТРОВ ФУНКЦИЯМ............................ 57
12. СТРУКТУРЫ И ОБЪЕДИНЕНИЯ............................................. 61
13. КЛАССЫ ............................................................................................ 64
14. ВВОД И ВЫВОД ИНФОРМАЦИИ В Ф А Й ЛЫ ................... 71
15. КЛАССЫ СТРОК И СТРОКОВЫХ ПОТОКОВ................... 77
15.1. Конструкторы стр о к.................................................................. 79
15.2. Арифметические операторы..................................................... 80
15.3. Потоки ввода (istream) .............................................................. 81
16. ДАТА И ВРЕМЯ В ПРОГРАММАХ НА С + + ........................ 84
17. ОБРАБОТКА ОШИБОК И ИСКЛЮЧЕНИЙ............................ 88
18. ДИНАМИЧЕСКОЕ ВЫДЕЛЕНИЕ ПАМ ЯТИ........................... 94
19. ТЕСТИРОВАНИЕ ПРОГРАММНОГО К О Д А .......................... 98
ЛАБОРАТОРНЫЕ РАБОТЫ ................................................................... 102
Лабораторная работа № 1 ...................................................................... 102
Лабораторная работа № 2 ...................................................................... 105
Лабораторная работа № 3 ...................................................................... 108
Лабораторная работа № 4 ...................................................................... 109
Лабораторная работа № 5 ....................................................................... 111
ИНДИВИДУАЛЬНОЕ ЗАДАНИЕ.......................................................... 114
Общие требования к разработке........................................................... 114
Представление результата выполнения индивидуального зада­
ния .............................................................................................................. 121
ПРИМЕРЫ ТЕСТОВЫХ ВОПРОСОВ................................................. 124
ЗАКЛЮ ЧЕНИЕ........................................................................................... 150
СПИСОК ЛИТЕРАТУРЫ......................................................................... 151
ВВЕДЕНИЕ

Программы определяют поведение и свойства любых информацион­


ных систем. От того, насколько эффективно работает программное обеспе­
чение, зависит безопасность всякой системы, использующей компьютер. По­
этому важно представлять базовые механизмы, которые определяют свой­
ства разрабатываемых программ. Эти свойства зависят от многих факторов,
начиная от используемого языка программирования, набора технологиче­
ских приемов программирования, и заканчивая уровнем организации ко­
манды программистов, реализующей проект. Данное учебное пособие пред­
назначено для освоения современных принципов программирования, ис­
пользуя для этого язык C++. Это объясняется следующим.
Язык C++ впитал в себя многие особенности современных языков
программирования, позволяющие использовать его в чрезвычайно разно­
образных областях. Такими областями являются встроенные системы
управления оборудованием, системы телекоммуникаций, мобильные
устройства, клиенты и серверы Интернет, информационные системы в эко­
номике и бизнесе. Языковые возможности C++ таковы, что позволяют со­
здавать программы как низкого, так и высокого уровня. Под низким уров­
нем понимают реализацию алгоритмов системного уровня, которые не за­
висят от прикладных задач. Примером подобного программирования могут
быть алгоритмы шифрования, контроля доступа к информационным ресур­
сам. Под высоким уровнем программирования понимают реализацию задач
специфического характера. Например, систем электронной коммерции в
Интернет. Компоненты систем такого типа представляют на страницах Ин­
тернет товары и услуги, осуществляют рекламные функции, выполняют
электронные платежи.
Технологии разработки программ на C++ поддерживаются про­
граммными инструментами, разработанными для разных операционных
систем. Практически любая современная операционная система имеет ком­
пилятор для языков С или C++. Многие из операционных систем поставля­
ются в виде исходных текстов, написанных на этих языках.
Методика оценки популярности базируется на статистике поиско­
вых запросов к наиболее популярным поисковым системам Google, Yahoo,

5
Введение

Bing, Amazon. Приведенные данные показывают, что «верхняя» часть рей­


тинга занята разновидностями языка С.
Рейтинг популярности языков программирования показывает, что
языки С и C++ в течение многих лет входят в «десятку» наиболее популяр­
ных языков программирования. По данным компании ТІОВЕ Software
В V[ 1], в 2019 г. рейтинг языков выглядел следующим образом:
Таблица 1
Рейтинг языков программирования
Декабрь Декабрь Язык
Рейтинг
2019 2018 программирования
1 1 Java 17,253%
2 2 С 16,086%
3 3 Python 10,308%
4 4 C++ 6,196%
5 6 C# 4,801%
6 5 Visual Basic .NET 4,743%
7 7 JavaScript 2,090%
8 8 PHP 2,048%
9 9 SQL 1,843%
10 14 Swift 1,490%
11 17 Ruby 1,314%

Данное учебное пособие не описывает язык C++. Этому посвящен


ряд учебников. Качество конечного результата программирования - про­
граммы - зависит от большого числа факторов, среди которых язык не счи­
тается определяющим. Поэтому использование C++ носит, скорее, иллю­
стративный характер. Основной целью пособия является изучение общих
особенностей программирования на алгоритмических языках, влияющих
на безопасность программных продуктов.
1. КАЧЕСТВО ПРОГРАММ

Реально используемая программа должна обладать требуемым каче­


ством. Эксплуатация некачественной программы таит в себе опасность по­
явления ущерба. Следовательно, уровень безопасности программы или си­
стемы программ оценивается степенью соответствия тому уровню каче­
ства, который диктуется областью применения.
Установить требуемый уровень качества - задача непростая. Поня­
тие качества в значительной степени зависит от прикладной области. Каче­
ство зависит от набора частных показателей (параметров), которые зача­
стую трудно оценить. Кроме того, поведение отдельных показателей по-
разному влияет на общий показатель. Это заставляет искать компромисс­
ные варианты сочетания параметров, в которых улучшение по одним ком­
пенсируется ухудшением по другим.
Всякая программа обладает набором параметров качества. Рассмот­
рим наиболее часто употребляемые на практике.

1.1. Правильность программы

Правильной считается та программа, которая соответствует исход­


ному заданию на разработку (спецификации, рис. 1).
Степень соответствия может оцениваться как количественно, так и
качественно. Количественная оценка может даваться в процентах. Напри­
мер, правильная на 50 % программа соответствует только половине задан­
ных требований. Легко видеть, что такой способ измерения правильности
не дает полного представления о качестве программы. Может оказаться не
выполненным настолько важное требование, что оцениваемая программа
окажется совершенно бесполезной либо чрезвычайно опасной.
Качественные оценки правильности - это выражения вида «соответ­
ствует», «почти соответствует», «слабо соответствует», «не соответствует»
и т.д. Правила качественной оценки оказываются на практике достаточно
сложными и зависят от ряда количественных оценок. Например, программа
может классифицироваться как «слабо соответствующая» спецификации,
если не выполнено хотя бы одно из важных требований либо не соблюда­
ется достаточно много некоторых специальных ограничений.
7
1. Качество программ

9■

Требования
к программе (техническое
Программа
задание)

Рис. 1. Соответствие программы требованиям

Задача оценки степени соответствия спецификации трудоемка.


Чтобы убедиться в правильности программы, разрабатывают тесты. Вся­
кий тест включает в себя описание того, что нужно знать и сделать для за­
ключения о правильности программы. Тест содержит:
1. описание состояния программы, и котором предполагается прове­
рить то или иное требование спецификации;
2. указание входных да.... . или воздействий, которым подвергается
программа или система в целом;
3. описание требуемого результата или поведения, которое должно
наблюдаться в случае соответствия спецификации.
Принципиальной трудностью проверки правильности является из­
менение спецификации в ходе разработки. На практике исходное задание
перед началом разработки имеет ряд неопределенностей, которые уточня­
ются по ходу работы. Такой процесс следует считать объективным ввиду
сложности решаемых задач.
Большинство разработчиков проводят неофициальное тестирова­
ние, когда пишут свои программы. После написания части кода (функции,
класса или фрагмента кода) разработчик пишет некий код для проверки
только что добавленной части, и. если тест пройден успешно, разработчик
удаляет код этого теста.
При тестировании стоит нацеливаться на 100%-ное покрыт ие кода,
ветвлений и циклов. Термин «покрытие кода» относится к количеству ис­
ходного кода программы, который был задействован во время тестирова­
ния. Термин «покрытие ветвлений» относится к проценту ветвлений, кот о­
рые были выполнены в каждом случае (положительном и отрицательном)

8
1.2. Надёжность программы

отдельно. Покрытие циклов (неофициально называемый «тест 0, 1, 2») со­


общает, что если у вас есть цикл в коде, то, чтобы убедиться в его работо­
способности, нужно его выполнить 0, 1 и 2 раза. Если он работает кор­
ректно во второй итерации, то должен работать корректно и для всех по­
следующих итераций (3, 4, 10, 100 и т.д.).
Модульные тесты позволяют разработчикам и тест-инженерам
быстро искать логические ошибки в методах классов для проектов на язы­
ках С#, Visual Basic и C++. С помощью окна Обозреватель тестов вы мо­
жете создавать и выполнять модульные тесты для C++ в программе Visual
studio 2017 и в более поздних версиях.
Общее число тестов зависит от масштаба разрабатываемой про­
граммы или системы. Затраты на тестирование могут составлять до 40 %
от стоимости всего проекта.

1.2. Надёжность программы

Надёжность - это способность системы работать без сбоев и отказов


в течение заданного интервала времени. Данное определение для техниче­
ских систем дается ГОСТ [3]. Может показаться, что это определение не
применимо к программам, поскольку программный код не подвержен дей­
ствию факторов внешней среды. Однако это не так. Причиной ненадежно­
сти программ являются наличие в программном коде не выявленных оши­
бок. Если качественно изобразить поведение вероятности отказа про­
граммы (рис. 2), то оно дает практически наблюдаемую картину: чем
дольше работает программа, тем вероятней появление сбоя или отказа из-
за не выявленной ошибки.
Количественно надежность характеризуют набором стандартных
показателей. Трудность достоверного оценивания надежности программ в
том, что ошибки проявляются на определенных сочетаниях входных дан­
ных, перебрать которые полностью абсолютно невозможно. Надежность
оценивается путем тестирования. Поскольку исчерпывающее тестирование
невозможно, на практике иногда придерживаются некоторых эмпириче­
ских правил оценки уровня надежности. Например, считается, что профес­
сионально написанный программный код содержит не более 10-12 не вы­
явленных ошибок на 1000 строк кода.

9
1. Качество программ

Ротказа

At

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

1.3. Время получения результата

Данный показатель может иметь несколько интерпретаций и, соот­


ветственно. способов измерения.
Если используют такой показатель, как время реакции программы на
внешнее событие, то временем получения результата считается интервал
между изменением входных данных и соответствующим изменением вы­
ходных. Время реакции важно для систем реального времени: программы
должны формировать результат в темпе, соответствующем изменениям
внешней среды.
Если область использования программы такова, что важно среднее
время получения результата, оценивают производительность (пропускную
способность) программы. Производительность определяется как количе­
ство данных или задач определенного типа, обрабатываемых программой
в ед........ времени.
1Іоказатель времени получения результата может быть получен либо
расчетным путем, либо экспериментально. В последнем случае применя­
ются тесты производительности, состоящие из «смеси» данных разных ти­
пов. 1Іодготовка таких данных является ответственной задачей, поскольку
неадекватность тестов приводит к ошибке оценки.

1.4. Используемые ресурсы

Всякая программа использует оперативную память, специализиро­


ванные процессоры, память внешних устройств, пропускную способность
канала связи и сетевые серверы (рис. 3). Эти объекты относят к ресурсам.
10
1.5. Защита

1Іоказатель используемых ресурсов носит количественный характер


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

і ;'| 1 I I. . I .4 . I. ■ ■ ■ ■ ■ ! І, Ѵ • ••

**’•'* i ' : * 1 ' ■i j ■•' i1■»


устройств X

П рограм м а

К.э И.) ЛЫ ГН и л-

С пе циал и зи ров анн ы е


;.*•11и•*'• :,.н

Рис. 3. Программа и используемые ресурсы

Оце.....зают используемые ресурсы нагрузочными тестами. Тест за­


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

1.5. Защита

Программа считается защищенной, если она способна противосто­


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

11
1. Качество программ

Кроме перечисленных, существует ряд других частных показателей


качества:
• удобство диалогового интерфейса;
• перестраиваемость (реконфигурирование);
• отказоустойчивость;
• возможность расширения функций;
• переносимость на другие аппаратные платформы и т.д.
Эти показатели могут играть второстепенную роль в глобальной
оценке качества. Однако их уровни также нуждаются в оценке, что реали­
зуется тестированием.

Рис. 4. Эффективность системы защиты

Показатели защиты могут быть как качественными, так и количе­


ственными. Уровень защиты определяется тестированием.
2. ОСНОВНЫЕ ЭТАПЫ РАЗРАБОТКИ ПРОГРАММ

Ниже перечислены основные этапы разработки программ:


• Постановка задачи
• Моделирование
• Архитектурное проектирование
• Кодирование и отладка
• Тестирование
• Опытная эксплуатация
На сегодняшний день существует много программных технологий,
каждая из которых реализует перечисленные этапы некоторым специаль­
ным образом. Этапы могут разделяться на отдельные стадии, переходы
между этапами могут сопровождаться проведением особых процедур, од­
нако общая логика разработки применима к программам любого масштаба.
Первый этап разработки - это выполнение постановки задачи. Ре­
зультатом постановки задач является определение требований к разрабаты­
ваемой программе. Этот результат обычно фиксируется в техническом за­
дании (спецификации).
На этапе постановки задачи изучают известные средства решения
поставленной задачи, оценивают существующие технологии. Правиль­
ность выбранного пути разработки программы во многом зависит от опыта
разработчика, его знаний и умений. Данный этап отличается нестандартно­
стью принимаемых решений. Цена ошибки здесь максимальна, поскольку
ставит под угрозу выполнение всего проекта.
На этом этапе определяются требования к точности решения и воз­
можные допущения.
В табл. 2 показано примерное содержание требований, формулируе­
мых по окончании этапа.
Таблица 2
Содержание требований к программе
1 Что даст пользователю программа
2 Требования к входной информации
3 Требования к системной платформе (аппаратура и операционная система)
4 Требования к представлению результатов
5 Параметры качества конечного продукта с методикой их проверки

13
2. Основные этапы разработки программ

Второй этап разработки - моделирование - необходим для оценки


реализуемости выбранного пути. Виды моделей могут быть самыми раз­
ными: математические, информационные, экономические, имитационные
и т.д. Не исключено макетирование, т.е создание программы, реализующей
частично функции конечного варианта разработки.
Чаще всего задача, предназначенная для решения на персональном
компьютере, должна быть записана в математической формулировке, т.е.
выражена в терминах формально определённых в математике понятий с
четко определёнными свойствами. Условие задачи задается в виде уравне­
ний, либо в виде последовательности формул или логических соотноше­
ний. Основным компонентом второго этапа является построение математи­
ческой модели.
Моделирование снижает опасность ошибки выбора средств реализа­
ции проекта. По результатам моделирования может оказаться необходи­
мым возвратиться на предыдущий этап и изменить постановку задачи.
Если одна и та же задача может быть решена с помощью различных
методов, выбирают подходящий по уровню точности решения, быстроте
получения результата, занимаемому объём памяти для выполнения про­
граммы и хранения результатов. Также учитывается сложность программ­
ной реализации метода.
Выделяют точные и численные методы. Сущность точных методов
состоит в последовательности выполнения арифметических и логических
действий, позволяющих получить точное решение (пример - возведение
числа в степень). Численные методы используются для большинства задач,
встречающихся в инженерной практике. Они обеспечивают отыскание ре­
зультата с требуемой точностью.
Стоит учитывать, что в некоторых случаях пригодность избранного ме­
тода можно определить лишь на последующих этапах разработки программы.
Этап архитектурного проектирования состоит в построении логи­
ческой структуры программы или системы, определении элементов и свя­
зей между ними. Трудоемкость дальнейшей разработки во многом зависит
от принятых архитектурных решений, поскольку они определяют перечень
уже готовых компонентов и новых, подлежащих созданию. Здесь большую
роль играет знание разработчиком особенностей существующих библиотек
программ и компонентов.

14
2. Основные этапы разработки программ

На этапе кодирования и отладки создается программный код си­


стемы или программы. Работа на этом этапе ведется в выбранной системе
(среде) программирования. Система программирования - это программ­
ный комплекс, автоматизирующий все процессы создания программ. В
данном учебном пособии предполагается использование среды програм­
мирования Microsoft Visual Studio. Современные системы программиро­
вания позволяют:
• создавать и вести проекты программ. Проект программы - это ин­
формационная структура, включающая как исходный код на выбранном
языке программирования (текст программы), так и служебные данные, не­
обходимые для управления процессом создания программы;
• работать с исходным кодом программ. Эти функции охватывают
действия от простого редактирования до отслеживания версий кода;
• осуществлять отладку программы - выполнять по шагам, останав­
ливать в нужных точках, контролировать значения переменных, вызовов
подпрограмм;
• создавать тесты отдельных компонентов;
• использовать специализированные программные инструменты.
Например, подключаться к базам данных, Интернет-серверам, другим про­
ектам, вести совместную работу над проектом несколькими разработчиками.
Этап тестирования направлен на оценку качества разработанной
программы. Не протестированный программный продукт является чрезвы­
чайно опасным: не известно, насколько соответствует он спецификации и
каков реальный уровень ошибок имеет место в его работе.
Основными источниками ошибок являются поверхностная прора­
ботка математической модели или алгоритма решения задачи; нарушение
соответствия между блок-схемой или записью алгоритма на алгоритмиче­
ском языке и программой, записанной на языке программирования; невер­
ное представление исходных данных; невнимательность при наборе про­
граммы и исходных данных на устройства ввода.
Нарушение соответствия между детально разработанной записью
алгоритма в процессе кодирования программы относится к ошибкам, про­
ходящим вследствие невнимательности программиста.
Потенциальные ошибки делятся на два вида:
15
2. Основные этапы разработки программ

- синтаксические (ошибки в записи конструкций языка программи­


рования: чисел, переменных, функций, выражений, операторов, меток, под­
программ). Пример: пропуск точки с запятой в конце строки;
- семантические (ошибки, связанные с неправильным содержанием
действий и использованием недопустимых значений величин). Пример: не­
верно выбранный тип данных, приведший к потере знаков.
На этапе опытной эксплуатации изучают поведение разработан­
ной программы в реальных условиях эксплуатации. По сути, данный этап
следует отнести к тестированию. Могут применяться два варианта тести­
рования:
• альфа-тестирование, когда реальные условия воспроизводятся со­
трудниками организации-разработчика;
• бета-тестирование, когда программа передается сторонним экспер­
там для использования с условием фиксации выявленных ошибок.
3. АЛГОРИТМИЗАЦИЯ

Программирование на алгоритмическом языке предполагает, что


разработчик программы представляет себе последовательность действий,
которую должна выполнять программа. Последовательность действий, ко­
торая приводит к получению результата, называют алгоритмом. Заметим,
что существуют языки программирования, использование которых не
предусматривает формулировку алгоритма. Однако без концепции алго­
ритма при программировании на C++ обойтись невозможно.
Разрабатывая алгоритм, необходимо соблюдать следующие требова­
ния к нему:
1. Однозначность описания. Выбранный разработчиком способ описа­
ния не должен допускать многозначности толкования отдельных действий
алгоритма. На практике избежать неоднозначности достаточно трудно и в
этом кроется опасность появления ошибок при разработке программы.
2. Результативность (конечность). Предполагается, что созданный
алгоритм должен давать результат за конечное число шагов. Несоблюдение
данного требования порождает опасность «зависания» программы.
3. Детерминированность. Требование состоит в том, что одни и те же
входные данные должны давать один и тот же результат по окончании ал­
горитма. Если это не так, то невозможно отличить правильный результат
от ошибочного.
Построение алгоритмов относится к области интеллектуальной дея­
тельности и трудно формализуется. Поэтому точных рекомендаций о том,
как строить алгоритмы, не существуют. Ниже приведены некоторые стра­
тегии поиска решений, которые применяют при алгоритмизации:
• Описание примеров и их обобщение.
• Сопоставление с известным образцом.
• Упростить, затем усложнить.
• От частного к общему.
• Выбор структуры данных.
Стратегия Описание примеров и их обобщение заключается в том,
чтобы поставленную задачу попробовать решить на нескольких примерах

17
3. Алгоритмизация

с тем, чтобы выработать затем общий алгоритм решения. Здесь важна ви­
зуализация примеров: можно использовать рисунки и схемы. Они могут
натолкнуть на идею алгоритма.
Сопоставление с известным образцом предполагает, что разработ­
чик знает ряд алгоритмов и пытается найти среди них аналогичный тому,
который требуется построить.
Стратегия Упростить, затем усложнить основана на том, чтобы ис­
ходную задачу представить в некотором упрощенном виде, позволяющем
составить алгоритм. Затем пытаются усовершенствовать алгоритм так,
чтобы он учитывал первоначально сделанные упрощения.
Стратегия От частного к общему состоит в следующем: текущий
результат пытаются получить, комбинируя более простые предыдущие ре­
зультаты работы алгоритма.
Стратегия Выбор структуры данных состоит в том, чтобы решить
задачу выбором такой структуры данных, которая, по сути, заменяет алго­
ритм поиска решения выбором из памяти готового результата.
Всегда ли нужно описывать алгоритмы перед разработкой про­
граммы? Категоричного утвердительного ответа здесь дать нельзя. Описа­
ние алгоритма полезно разработчику ровно настолько, насколько позво­
ляет справиться с сложной задачей. «Простые» задачи обдумываются и ре­
ализуются непосредственно написанием программного кода. Простота
оценивается в 5-10 строк кода. Если речь идет о сложных задачах, то опи­
сание алгоритма необходимо по нескольким причинам:
• на этапе постановки задачи для фиксации и обдумывания разных
вариантов решения;
• на этапе моделирования для уточнения и детализации действий,
выполняемых программой;
• при архитектурном проектировании алгоритмами описывают
связи между элементами системы;
• при кодировании и отладке коллективной работы.
Варианты описания алгоритмов приведены ниже: Естественный код;
Псевдокод; Блок-схемы.
Описание алгоритмов на естественном языке выглядит как нуме­
рованный список действий. Пример алгоритма работы калькулятора:

18
3. Алгоритмизация

1. Определить операцию, соответствующую нажатой кнопке клавиа­


туры.
2. Если операция соответствует вводу данных, отобразить эти данные
на экране калькулятора.
3. Если операция соответствует вычислению, выполнить его и отоб­
разить результат на экране. Затем перейти к п. 1.
4. Если операция является выключением калькулятора, то очистить
экран и отключить электропитание.
Описание алгоритма на естественном языке - наиболее универсаль­
ный вариант представления алгоритма.
Таблица 3
Пример псевдокода
While (НЕ КонецФайла())
{
СчитатьСтроку ()
ВыделитьВтороеПоле()
НомерКонтракта[і]=ВтороеПоле
І=і+1
1__________________________________
Использование псевдокода характерно для профессиональных
групп программистов. Пример такого описания приведен в табл. 3.
Псевдокод представляет собой компактный, как правило, нефор­
мальный язык описания алгоритмов. В псевдокоде используются ключевые
слова императивных языков программирования (С, C++, Java), но опуска­
ются несущественные для понимания алгоритма подробности, а также спе­
цифический синтаксис. Отличительной особенностью псевдокода является
использование языковых конструкций языков программирования.
Блок-схемы относятся к способам графического изображения алго­
ритмов. На рис. 5 показаны элементы блок-схем, соответствующие стан­
дарту. Надписи внутри блоков не стандартизованы, рекомендуется делать
их на естественном языке.
При описании алгоритмов давно и успешно используются блок-
схемы (Basic Flowchart). Построение блок-схем алгоритмов регламентиру­
ется ГОСТом 19.701-90 (ИСО 5807-85) "Единая система программной до­
кументации. Схемы алгоритмов программ, данных и систем. Условные

19
3. Алгоритмизация

обозначения и правила выполнения". Данный государственный стандарт


составлен на основе международного стандарта "ISO 5807-85. Information
processing - Documentation symbols and conventions for data, program and sys­
tem flowcharts, program network charts and system resources charts".
Согласно ГОСТ 19.701-90 под схемой понимается графическое
представление определения, анализа или метода решения задачи. С помо­
щью схем можно отобразить как статические, так и динамические аспекты
системы. Символы, приведенные в государственном стандарте, могут ис­
пользоваться в следующих типах схем:
- схемы данных определяют последовательность обработки данных
и их носители;
- схемы программ отображают последовательность операций в
программе (по сути, это и есть блок-схемы алгоритмов в традиционном
понимании);
- схемы работы системы отображают управление операциями и по­
токи данных в системе;
- схемы взаимодействия программ отображают путь активации про­
грамм (модулей) и их взаимодействие с соответствующими данными;
- схемы ресурсов системы отображают конфигурацию блоков дан-
шах и обрабатывающих блоков.

Рис. 5. Элементы блок-схем

20
3. Алгоритмизация

Разработка блок-схем выполняется на этапах проектирования и до­


кументирования согласно каскадной модели разработки ПО, которая явля­
ется устаревшей, потому что зачастую сопровождается ошибками на эта­
пах проектирования.
Тем не менее, в ряде случаев, создание программы невозможно без
рисования блок-схем, так как представляет собой один процесс - суще­
ствуют визуальные языки программирования, такие как ДРАКОН (русский
алгоритмический язык). Также блок-схемы используются для верификации
алгоритмов или формального доказательства их корректности методом ин­
дуктивных утверждений Флойда (первый этап доказательства полной кор­
ректности программы).
4. ИСПОЛНЕНИЕ ПРОГРАММ

Всякая программа исполняется одним или несколькими процессо­


рами. Процессоры - электронные цифровые устройства, которые реали­
зуют принцип программного управления. Независимо от того, на каком вы­
сокоуровневом языке написана программа, она должна быть переведена в
коды команд конкретного процессора.
Принцип программного управления заключается в следующем: в
вычислительной системе есть запоминающее устройство, которое хранит
информацию двух видов - команды и данные. Различие в видах не опреде­
ляется способом кодирования, а зависит от интерпретации.
Интерпретация команд обеспечивается устройством управления.
Конечный результат обработки информации определяется только коман­
дами программ.
Данные представляются и обрабатываются соответственно логике,
которая принята для команд конкретного процессора.
Всякая команда процессора состоит из полей. Поле - это набор би­
тов, который имеет строго определенные позиции размещения. Практиче­
ски всякая команда имеет поле кода операции. Код в этом поле содержит
номер действия, которое должно быть выполнено над операндами. Поля
операндов могут содержать как непосредственные данные, так и информа­
цию, чтобы найти их во внешней памяти.
Любой код, который должен исполнить процессор, помещается в ис­
полняемые файлы. В операционной системе Windows такие файлы имеют
расширение EXE, DLL, СОМ. Кроме непосредственно процессорного кода,
эти файлы содержат служебную информацию, необходимую операцион­
ной системе для запуска и исполнения программного кода (рис. 6).
Для получения исполняемого кода должны быть выполнены две ос­
новные операции:
• откомпилированы файлы с исходным кодом программы (напри­
мер, тексты программ на C++). Продукт компиляции - объектный код -
представляет собой промежуточный результат и сохраняется в файлах с
расширением OBJ;
• объектные файлы скомпонованы со служебными файлами и фай­
лами библиотеки программирования в файлы с исполняемым кодом.

22
4. Исполнение программ

Рис. 6. Исходный и исполняемый код

Исполнение программного кода осуществляется при участии испол­


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

Рис. 7. Исполнение программ


5. СТРУКТУРА
ПРОГРАММЫ НА C++

Программа на языке C++ включает в себя программный код и дирек­


тивы препроцессора.
Препроцессор - это специализированная программа среды програм­
мирования, которая запускается перед компиляцией и предназначена для
обработки текста. Препроцессор выполняет директивы, которые начина­
ются со знака #. Каждая директива имеет наименование и параметры.
Например #include в качестве параметра содержит имя файла, текст
из которого будет подставлен на место самой директивы (#include
“stdafx.h”).
Отправной точкой выполнения любой С++-программы является
функция main(). Функция содержит четыре элемента:
1. возвращаемый тип (в нашем случае int);
2. имя функции (main);
3. список параметров, заключенный в круглые скобки (в данном слу­
чае список пуст);
4. тело функции, заключенное в фигурные скобки и представляющее
собой блок инструкций.
Инструкцией называется часть программы, определяющая действие
и не являющаяся директивой препроцессора.
Программный код состоит из функций, описание которых включают
в себя:
1. тип результата (возвращаемый);
2. имя функции - произвольную комбинацию символов, начинаю­
щихся с буквы. Есть ряд ограничений на использование специальных сим­
волов. Не допускаются употребление пробела, запятой (,), точки с запятой
(;), символа #;
3. список параметров. Число параметров не ограничивается. Спи­
сок - последовательность пар наименования типа и параметра, разделяе­
мые запятыми;
4. тело функции - программный блок, т.е. любая последовательность
операторов языка или вызовов функции, заключённая в фигурные скобки.

24
5. Структура программы на C+ +

Таблица 4
Пример программы на C++
include “stdafx.h”
int_main (int argc, _TCHAR* argv [])
{
printf (“Hello, world !”);
return 0;
______________________________________________________
Пример описания функции, созданной пользователем:
int MyFunction (int A, int В)
{
return (А+В);

Существует стартовая функция, т.е. с нее исполняющая система


начнет выполнение программного кода. Есть соглашение, согласно кото­
рому стартовая функция имеет уникальное имя, которое не может исполь­
зоваться в других случаях.
Тело функции содержит описание переменной, указание типа и
имени. Описание может размещаться в любом месте до первого использо­
вания этой переменной. В теле программы размещаются вызовы библио­
течных функций и функций, созданных пользователем - программистом.
Если функция не возвращает никакого значения, то она должна
иметь тип void (такие функции иногда называют процедурами).
При объявлении функции, после ее типа должно находиться имя
функции и две круглые скобки - открывающая и закрывающая, внутри
которых могут находиться один или несколько аргументов функции, ко­
торых также может не быть вообще. После списка аргументов функции
ставится открывающая фигурная скобка, после которой находится само
тело функции. В конце тела функции обязательно ставится закрывающая
фигурная скобка.
Создаваемые пользователем функции способны выполнять любые
действия, как и основная функция, являющаяся точкой ввода программ.
Пример пользовательской функции, меняющей местами значения
элементов а и Ь:

25
5. Структура программы на C+ +

void swap (int а, int b){


int c = a;
a = b;
b = c;

Вызовы всякой функции включают в себя фактический параметр,


т.е. те значения, которые подлежат обработке. В тексте функции использу­
ются формальные параметры, с помощью которых обрабатываются любые
значения, переданные функции (табл. 5).
Таблица 5
Формальные и фактические параметры функций
# include “stdafx.h”
# incude < iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
char cSymbol [100];
cin » cSymbol;
MyPrint (cSymbol);
return 0;
}
void MyPrint (char* c String)
{
char HelloString[]=”Hello,
cout « endl « HelloString;
_______co u t« cString « “ ! “; }___________________________________
Пользовательские функции иначе называют подпрограммами.
В подпрограммы выделяют фрагменты кода, повторяющиеся в логике про­
граммы несколько раз. Использование пользовательских функций позво­
ляет сделать программу более короткой. Пользовательские функции - это
готовый к использованию сторонним разработчиком фрагмент кода про­
граммы, который разработчики могут легко передавать друг другу и ис­
пользовать без дополнительной доработки.
При создании собственной функции следует записывать их объявле­
ние до первого использования. Обычно такие объявления размещаются в
начале программного кода. Объявление функции содержит указание типа
результата, её имени и параметра (табл. 6).

26
5.1. Поточный ввод-вывод в C+ +

Таблица 6
Объявление и определение функции
# include “stdafx.h”
# incude < iostream>

using namespace std;


int _tmain(int argc, _TCHAR* argv[])
{
char cSymbol[100];
cin » cSymbol;
MyPrint (cSymbol);
return 0;
}
void MyPrint (char* cString)
{
char Hello String []- ’Hello,
cout « endl « HelloString;
co u t« cString « “ !
1___________________________________________________________

5.1. Поточный ввод-вывод в C++

Как и язык программирования С, C++ не имеет встроенных средств


ввода-вывода. Язык С для этих целей использует библиотеку stdio.h.
В C++ разработана новая библиотека ввода-вывода iostream, исполь­
зующая концепцию объектно-ориентированного программирования:
#include <iostream>
Библиотека iostream определяет три стандартных потока:
• сіп - стандартный входной поток;
• cout - стандартный выходной поток;
• сегг - стандартный поток вывода сообщений об ошибках.
Для их использования в Microsoft Visual Studio необходимо пропи­
сать строку:
using namespace std;
Для выполнения операций ввода-вывода переопределены две опера­
ции поразрядного сдвига:

27
5. Структура программы на C+ +

» получить из входного потока


« поместить в выходной поток

5.2. Вывод информации

co u t« значение;
Здесь значение преобразуется в последовательность символов и вы­
водится в выходной поток:
co u t« п;
Возможно многократное назначение потоков:
co u t« 'значение Г « 'значение2'« . . . « 'значение п';

5.3. Ввод информации

сіп » идентификатор;
При этом из входного потока читается последовательность символов
до пробела, затем эта последовательность преобразуется к типу идентифи­
катора, и получаемое значение помещается в идентификатор.
Возможно многократное назначение потоков:

сіп » переменнаяі » переменная2 » . . . » переменнаяп;

5.4. Ввод символьных строк

По умолчанию потоковый ввод сіп вводит строку до пробела, сим­


вола табуляции или перевода строки.

5.5. Манипуляторы потока

Функцию-манипулятор потока можно включать в операции помеще­


ния в поток и извлечения из потока ( « , » ) . Для использования манипуля­
торов с параметрами в программу необходимо включить заголовочный
файл iomanip.h.

#include < iomanip.h >

28
5.5. Манипуляторы потока

Манипуляторы могут использоваться в составе выражений ввода /


вывода.
Таблица 7
Стандартные манипуляторы ввода/вывода C++

Манипуля гор Назначение Ввод/вывод

Ввод/вывод данных в деся і нчной


dec ввод и вывод
форме
Вывод символа новой строки с пе­
endl редачей в поток всех данных из бу­ вывод
фера
ends Вывод нулевого символа вывод

Передача в поток содержимого бу­


flush вывод
фера
Ввод/вывод данных в шестнадца­
hex ввод и вывод
тиричной системе
Ввод/вывод данных в восьмерич­
oct ввод и вывод
ном форме
resetiosflags(long f) Сбрасывает флаги, указанные в f ввод и вывод
Устанавливает базу счисления рав­
setbase(int base) вывод
ной параметру base
Устанавливает символ заполнения
setfill(int eh) вывод
равным eh
Устанавливает флаги, указанные в
setiosflags(long f) ввод и вывод
f
Устанавливает число цифр после
setprecision(int p) вывод
запятой

Устанавливает ширину поля рав­


setw(int w) вывод
ной W

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


ws ввод
разделитель

Практическое задание 1. Консольные приложения ввода-вывода


Задание: ввести данные в указанном формате с клавиатуры.

29
5. Структура программы на C++

Таблица 8
Варианты для практического задания 1

Входные данные Представление выходных данных
вар.
i 10 целых простых чисел Вывести числа в шестнадцатеричной
типа int системе счисления.
Все числа записываются через пробел,
если длина полученной строки больше
15 символов, выполнить перенос на но­
вую строку
2 15 целых чисел типа short со После цифры 5 выполнять вертикаль­
знаком в шестнадцатеричной ную табуляцию
системе счисления
3 10 целых чисел типа int со Максимальное количество символов: 25.
знаком в восьмеричной си­ Вывести число в 8-СИ. Если его длина
стеме счисления превышает 25 символов, то необходимо
вывести 25 первых символов числа
4 10 целых чисел типа int со В полученной строке все цифры 4 выво­
знаком в восьмеричной си­ дить в апострофах.
стеме счисления Пример: 0х0”4”21
5 15 целых чисел типа longint со Все числа записываются через пробел,
знаком в шестнадцатеричной если длина полученной строки больше
системе счисления 10 символов, выполнить перенос на но­
вую строку
6 10 чисел с плавающей точкой Максимальное количество символов: 20
типа double (вещественный
формат двойной точности)
7 15 целых чисел типа int со Вывести 10 чисел, остальные отбросить
знаком в восьмеричной си­
стеме счисления
8 10 целых чисел типа int со В полученной строке все цифры 8 выво­
знаком в восьмеричной си­ дить на экран в апострофах
стеме счисления
9 10 целых чисел типа signed Показать знак для положительных чи­
shortint сел
10 15 целых чисел типа longint со После каждой цифры 2 выполнять вер­
знаком в шестнадцатеричной тикальную табуляцию
системе счисления

30
5.5. Манипуляторы потока

Окончание табл. 8

Входные данные Представление выходных данных
вар.

п 20 целых чисел типа unsigned Вывести первые 15 чисел, осталь­


longint ные отбросить
12 10 целых чисел типа int со знаком в Вывести 30, остальные отбросить
восьмеричной системе счисления
3 10 целых чисел типа int со знаком в Каждые 20 символов выполнять
десятичной системе счисления перенос строки
14 Вещественный формат двойной Вывести числа, больше чем А
точности (10 чисел с плавающей
точкой типа double). *Ввести с кла­
виатуры число А для сравнения
15 15 целых чисел типа short со знаком После каждой цифры 9 выполнять
в шестнадцатеричной системе счис­ вертикальную табуляцию
ления
6. ПЕРЕМЕННЫЕ ПРОГРАММЫ
И ОБЛАСТИ ИХ ДЕЙСТВИЯ

Всякая переменная программы “возникает” в момент выделения па­


мяти для размещения её значения. Переменная “исчезает”, когда выделенная
память возвращается в разряд свободных ресурсов памяти. Интервал вре­
мени между этими событиями называют “временем жизни” элемента, а уча­
сток программного кода, где используется переменная - областью действия.
Область действия переменной определяются следующим:
1. границей программного блока (табл. 9). В языке C++ программ­
ный блок заключен в фигурные скобки. Переменная действует во всех вло­
женных блоках. В примере это целочисленная переменная с именем х;
2. телом функции, для которой объявленные переменные являются
параметрами (табл. 10). Параметр х функции SomeFunction может исполь­
зоваться как переменная только внутри этой функции;
Таблица 9
Зона действия переменной внутри программного блока
Программный блок
{
int X;
{

Область видимости переменных - это те части программы, в которой


пользователь может изменять или использовать переменные в своих нуждах.
В C++ существуют отдельные блоки, которые начинаются с
открывающей скобки ({) и заканчиваются соответственно закрывающей
скобкой (}). Такими блоками являются циклы (for, while, do while) и
функции.
Если переменная была создана в таком блоке, то ее областью
видимости будет являться этот блок от его начала (от открывающей
скобки - { ) и до его конца (до закрывающей скобки - } ), включая все
дочерние блоки созданные в этом блоке.

32
6. Переменные программы и области их действия

Таблица 10
Зона действия переменной-параметра функции
Тело функции
char SomeFunction(int X)
{
intY ;

static int r=0;


___________1_________________________________________________
Глобальными переменными называются те переменные, которые
были созданы вне тела какого-то блока.
Таблица 11
Глобальная переменная в файле
Файл *.срр
int Z;
char SomeFunction(int X)
{
intY;
Y = Z +100;
}
void MyFunction( char s)
{
intY;
Y = Z -l;

__________ 1______________________________________________________
В языке C++ существует возможность сохранять значения
переменной после завершения функции и последующим вызовом. Это
обеспечивается, если переменная описана как статическая с помощью
ключевого слова static.
Зона действия глобальных переменных ограничивается функциями
файлов, в которых размещены определения этих функций (табл. 11).
7. ТИПЫ ДАННЫ Х

Язык C++ относится к типизированным языкам программирования.


Всякая переменная программы должна обязательно иметь тип. Типизиро­
ванные языки по сравнению с не типизированными дают более надежные
программы. Опасность не типизированных программ - в возможном некор­
ректном преобразовании данных.
Типы данных - это разновидность данных, отличающихся специ­
альной структурой и набором допустимых для выполнения операций.
Операции считаются допустимыми, если их результатом является объект
того же типа. Все типы языка C++ можно разделить на основные и состав­
ные. Основные типы данных используются для представления целых, ве­
щественных, символьных и логических величин. К составным типам от­
носятся массивы, перечисления, функции, структуры, ссылки, указатели,
объединения и классы.
В табл. 12 показан пример встроенных типов C++. Встроенные или
простые типы языка C++ служат для построения более сложных типов.
Операции, которые допустимы над простыми типами, позволяют програм­
мировать любые алгоритмы, однако простота операций порождает слож­
ные программы.
Таблица 12
Пример встроенных типов языка C++
char int
short long
float double
Простые типы именуются следующим образом:
• char - символьный;
• int - целое число;
• short - короткое целое число;
• long - большое целое число;
• float - числа с плавающей точкой;
• double-числа с плавающей точкой двойной точности.
Размер объектов в байтах может быть определен с помощью функ­
ции sizeof (X), где X - наименование типа или любого объекта программы,

34
7.1. Символьный тип

занимающего память. В табл. 13 приведены фрагмент программного кода


и содержимое окна отладчика MS Visual Studio 2005, отображающего ре­
зультат определения числа байт для каждого типа.
Таблица 13
Размер типов для MS Windows 7 (32 бит)

Name Value
int а = sizeof (char); a 1

int b = sizeof (short); b 2

int c = sizeof (int); C 4


int d = sizeof (long); d 4
int e = sizeof (float); e 4
int f = sizeof (double); f 8

Структура всякого типа, относящегося к простым, характеризуется


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

7.1. Символьный тип

Символы на программном уровне представляются двоичными ко­


дами. Эти коды можно интерпретировать как целые числа. Поэтому над
символами допустимы все операции, которые допустимы для целочислен­
ного типа.
Символы от 0 до 31 в основном используются для форматирования
вывода. Большинство из них уже устарели.
Символы от 32 до 127 используются для вывода. Это буквы, цифры,
знаки препинания, которые большинство компьютеров использует для
отображения текста (на английском языке).

35
7. Типы данных

Соответствие между кодом-символом и его представлением зада­


стся таблицей стандартов кодирования. I Іа рис. 8 показан фрагмент таб­
лицы кодирования соответственно стандарту ASCII.
C trl D ec H ex C har Code D ec H ex Char D ec H ex Char D ec H ex Char
л0 0 00 NUL 32 20 64 40 @ 96 60 •
АА 1 01 SO H 33 21 j 65 41 A 97 61 a
л6 2 02 STX 34 22 ** 66 42 В 98 62 b
АС 3 03 E TX 35 23 # 67 43 C 99 63 c
л0 4 04 EO T 36 24 $ 68 44 D 100 64 d
ЛЕ 5 05 EN Q 37 25 % 69 45 E 101 65 e
AF 6 06 A CK 38 26 & 70 46 F 102 66 f
AG 7 07 BEL 39 27 / 71 47 G 103 67 g
АН 8 08 BS 40 28 ( 72 48 H 104 68 h
ЛІ 9 09 HT 41 29 ) 73 49 I 105 69 i
AJ 10 0A LF 42 2A * 74 4A J 106 6A j
АК 11 0B VJ 43 2B + 75 4B К 107 6B k
AL 12 OC FF 44 2C 76 4C L 108 6C 1
АМ 13 0D CR 45 2D 77 4D M 109 6D m
AN 14 0E so 46 2E * 78 4E N 110 6E n
А0 15 OF SI 47 2F / 79 4F 0 111 6F 0
лр 0
16 10 D LE 48 30 80 50 P 112 70 P
"Q 17 11 DCl 49 31 i 81 51 0 113 71 q
AR 18 12 DC2 50 32 2 82 52 К 114 72 r
"S 19 13 DC3 51 33 3 83 53 S 115 73 s

Рис. 8. Стандарт кодирования ASCII

Организация IS( >(International Standardization Organization - Между­


народная Организация но Стандартам) приняла группу стандартов ISO
8859. Она определяет 8-битныс кодировки для разных групп языков. Так.
ISO 8859-1 - это Extended ASCII, таблица для США и Западной Европы. А
ISO 8859-5 - таблица для кириллицы (включая русский язык). Реально же
для русского языка применяются следующие кодировки:
- Code Page 866 (СР866). она же “DOS”.
- КС >11-8. Широко применяется также в операционных системах се­
мейства Unix, включая Linux.
- Code Page 1251. CP 1251. Window s-1251. Разработана компанией
Microsoft для поддержки русского языка в системе Windows.
Одним из национальных вариантов таблицы является стандарт
ISO 646 (ЕСМА-6). предусматривающий возможность размещения в ASCII
национальных символов. Для этого предлагается заменять символы « а ».
«[». «\». «]». «Л». «'». « ;». «I». « ;». «-». Также на месте знака решётки «#»

36
7.2. Числовые типы

может быть размещён символ фунта «£», а на месте символа доллара «$» -
знак валюты «и».
В табл. 14 показаны примеры программного кода, выполняющего
допустимые операции над переменными символьного типа.
Таблица 14
Допустимые операции над переменными символьного типа
char sl,s2,s3;
c o u t « ”Set symbol
c in » s l;
s2=’5 ’;
s3 = si + s2; /* ‘9’ + ‘5’ = ‘n ’ */
s3 = si —s2; /* ‘Z ’ - ‘5’ = ‘% ’ */
s3 = ‘\A ’;
s3 = ‘W;
cout « “Out s y m b o l « s3;

7.2. Числовые типы

Важнейшей характеристикой числовых типов является диапазон


представления. Если результат некоторого преобразования выходит за гра­
ницу диапазона, это считается ошибкой.
Ниже приведен пример диапазонов чисел, характерных для 16-бит­
ной операционной системы Windows:

char -128... 127


mt -32768... 32767
short -127... 127
unsigned int 0... 65535
long -2147483648... 2147483647
float 3.4E-38... 3.4E+38
double 1.7E-308... 1.7E+308
long double 3.4E-4932... 3.4E+4932
Если числовой тип имеет разрядность п, то количество различных
кодовых комбинаций определяется как 2й.
Если тип числа целое, то кодовые комбинации рассматриваются
напрямую как целые числа.
37
7. Типы данных

Если тип отображает числа с плавающей точкой, то одна часть раз­


рядов рассматривается как мантисса, а другая часть разрядов как порядок.
Поэтому те же кодовые комбинации интерпретируются по-другому. Типы
с плавающей точкой значительно расширяют диапазон используемых чи­
сел, но не увеличивают общее количество различных чисел. Иными сло­
вами, некоторые значения чисел не могут быть закодированы в принципе.
Таблица 15
Определение знака числа
unsigned int Z(unsigned int u) {
u —u » 31;
return u;
1_____________________________________
Каждый из способов представления чисел в вычислительных алго­
ритмах приводит к появлению погрешности.
Иногда сравнение чисел типа с плавающей точкой бывает неизбеж­
ным. В таком случае следует использовать операторы >, <, >= и <= только
если значения не очень близки. А вот если два операнда очень близки по
значениям, то результат уже может быть неожиданный.
При сравнении значений чисел с плавающей точкой всегда следует учи­
тывать точность вычислений. Более корректным является сравнение не чисел
между собой, а абсолютного значения разности между ними. В табл. 16 при­
веден пример программного кода, дающего разный результат при использо­
вании одних и тех же операций над различными типами переменных а и Ь.
В табл. 16 показаны данные отладчика, отображающего значения перемен­
ных а,Ь,с в точке останова на последней строке программного кода.
Таблица 16
Иллюстрация особенности сравнения чисел
float a,b,c; Name Value
а = 7 + 0.0000000001; а 7.0000000
b = 21/3; ь 7.0000000
if (а == b ) С 0.0000000
с = 0;
else
с = -1;

38
7.2. Числовые типы

Окончание табл. 16
double a,b,c; Name Value
3 = 7 + 0.0000000001; а 7.0000000001000000
b = 21/3; ь 7.0000000000000000
А С

С
И I
II с

-1.000000000000000

else
с = -1;

При выполнении арифметических операций над числами может воз­


никать переполнение разрядной сетки. Исполняющая система для C++ не
считает переполнение аварийной ситуацией, программа не прерывается.
При этом результат получает неожиданное значение. В табл. 17 показан
пример программного сложения двух целых чисел. Контроль за перепол­
нением возлагается на программиста.
Переполнение для чисел с плавающей точкой также не фиксируется
как аварийная ситуация. В качестве результата выводится специфическая
кодовая комбинация, которая не рассматривается как число. В табл. 17 это
значение изображено в окне отладчика. В математической библиотеке су­
ществует функция _finite(x), которая в качестве аргумента принимает зна­
чение выражения, а возвращает ложное значение, если имело место пере­
полнение.
Таблица 17
Переполнение для целых чисел
int a, b, с; Name Value
a=0x7fffffiF; a 21474833647
b=0x7fffffff; b 21474833647
с = а + b; C -2
double z = 9E100; Name Value
z=z*z*z*z; res 0
int res = Jrnite(z); z 1JINF00000000

Класс Safelnt защищает от переполнения целого числа в математи­


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

39
7. Типы данных

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

Практическое задание 2. Числовая обработка информации


Задание', длина последовательности целых чисел - случайное число
от 10 до 20 (число Ь). Последовательность заполняется в соответствии с
вариантом.
Числа вводятся пользователем, если не указано иное. Выполняется
проверка введенных значений. В случае ошибки выдается сообщение.
Таблица 18
Варианты для практического задания 2

Входные данные Представление выходных данных
вар.
i По заданию Числа, которые больше предыдущего
(первое число сравнить с последним)
2 По заданию Числа после цифры 3 игнорируются
3 Числа заполняются последова­ Четные числа
тельно от 0 до Ь—1
4 При вводе неверных значений Числа, которые больше предыдущего
вывести программу из режима (1е число сравнить с последним)
отказа
5 Числа генерируются случай­ Простые числа
ным образом
6 По заданию Нечетные числа
7 Числа заполняются последова­ Кратные 5
тельно от 1 до b
8 При вводе неверных значений Числа, которые больше предыдущего
вывести программу из режима (первое число сравнить с последним)
отказа
9 По заданию Совершенные числа
10 По заданию Выводятся первые 5 чисел, остальные
игнорируются
11 Числа заполняются последова­ Простые числа
тельно от 0 до b—1
12 Числа заполняются последова­ Выводятся первые 10 чисел, осталь­
тельно от 1 до b ные игнорируются программой

40
7.4. Неявное преобразование типа

Окончание табл. 18

Входные данные Представление выходных данных
вар.
13 При вводе неверных значений Совершенные числа
вывести программу из режима
отказа
14 Числа генерируются случай­ Числа, которые больше предыдущего
ным образом (первое число сравнить с последним)
15 По заданию Выводятся первые 7 чисел, остальные
игнорируются программой

7.3. Преобразование типов данных в C++

Преобразованием типа представляет собой процесс конвертации


значения из одного типа данных в другой. Преобразование типа может вы­
полняться в следующих случаях:
• присваивание или инициализация переменной значением другого
типа данных;
• передача значения в функцию, где тип параметра - другой;
• возврат из функции, где тип возвращаемого значения - другой;

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

7.4. Неявное преобразование типа

Неявное преобразование типов данных (или ещё «автоматическое


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

41
7. Типы данных

7.5. Числовое расширение

Когда значение из одного типа данных конвертируется в другой тип


данных побольше (по размеру и по диапазону значений), то это называется
числовым расширением. Например, int может быть расширен в long, a float
может быть расширен в double.
В C++ есть два типа расширений:
• Интегральное расширение (или ещё «целочисленное расшире­
ние»), Включает в себя преобразование целочисленных типов, меньших,
чем int (bool, char, unsigned char, signed char, unsigned short, signed short) в
int (если это возможно) или unsigned int.
• Расширение типа с плавающей точкой. Конвертация из float в double.
Интегральное расширение и расширение типа с плавающей точкой
используются для преобразования «меньших по размеру» типов данных в
типы int/unsigned int или double (они наиболее эффективны для выполнения
разных операций).

7.6. Числовая конверсия

Когда конвертируется значение из более крупного типа данных в


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

7.7. Обработка арифметических выражений

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


на отдельные подвыражения. Арифметические операторы требуют, чтобы
их операнды были одного типа данных. Чтобы это гарантировать, компи­
лятор использует следующие правила:
Если операндом является целое число меньше (по размеру/диапа-
зону) типа int, то оно подвергается интегральному расширению в int или в
unsigned int.
Если операнды разных типов данных, то компилятор вычисляет опе­
ранд с наивысшим приоритетом и неявно конвертирует тип другого опе­
ранда в соответствие к типу первого.
42
7.9. Явное преобразование типов данных

7.8. Приоритет типов операндов:

long double (самый высокий);


double;
float;
unsigned long long;
long long;
unsigned long;
long;
unsigned int;
int (самый низкий).
Чтобы узнать решающий тип в выражении, можно использо­
вать оператор typeid(), который находится в заголовочном файле typeinfo.

7.9. Явное преобразование типов данных

В C++ есть 5 типов операторов casts (или ещё «операторов явного


преобразования типов»):
С-style cast;
staticcast;
constcast;
dynam iccast;
reinterpretcast.
Оператор static cast лучше всего использовать для конвертации од­
ного фундаментального типа данных в другой. Преимуществом static_cast
перед оператором C-style cast является проверка его компилятором во
время компиляции, что усложняет возможность возникновения непредна­
меренных проблем, таких как изменение константы.

Практическое задание 3. Преобразование типов данных


Задание', выполнить проверку соответствия чисел заданному фор­
мату (максимальное значение должно быть вычислено программно). Вы­
полнить указанные операции по вариантам. Для вариантов с веществен­
ными числами выполнить неявное преобразование в тип int. Для вариантов
целыми числами выполнить явное преобразование в тип float. Числа вво­
дятся пользователем с клавиатуры.
43
7. Типы данных

Таблица 19
Варианты для практического задания 3

Входные данные Представление выходных данных
вар.
i 2 числа longlong. Опера­ Вывести числа в шестнадцатеричной си­
ция умножения стеме счисления
Все числа записываются через пробел, если
длина полученной строки больше 15 симво­
лов, выполнить перенос на новую строку
2 4 числа unsignedshort. После цифры 5 выполнять вертикальную
Операция сложения ин­ табуляцию
крементов чисел
3 3 чи сла unsignedint. О пе­ Максимальное количество символов: 25
рац ия получен ия остатка Вывести число в 8-СИ. Если его длина пре­
о т д еления вышает 25 символов, то необходимо выве­
сти 25 п ервы х символов числа
4 2 числа int. Операция сло­ В полученной строке все цифры 4 выводить
жения декрементов чисел в апострофах.
Пример: 0х0”4”21
5 3 чи сла float. О перация В се числа записываются через пробел, если
получен ия целой части от длина полученной строки больше 10 симво­
деления лов, выполнить перенос на новую строку
6 4 чи сла unsignedint. О пе­ Максимальное количество символов: 20
рация получен ия остатка
о т д еления
7 2 числа unsignedshort. Вывести 10 чисел, остальные отбросить
Вывести меньшее из чисел
8 3 числа longdouble. Опе­ В полученной строке все цифры 8 выводить
рация деления на экран в апострофах
9 2 числа float. Операция де­ Показать знак для положительных чисел
ления
10 2 числа double. Операция После каждой цифры 2 выполнять верти­
сложения инкрементов чи­ кальную табуляцию
сел
11 3 числа unsignedlonglong. Вывести первые 15 чисел, остальные отбро­
Операция сложения декре­ сить
ментов чисел

44
7. 9. Явное преобразование типов данных

Окончание табл. 19

Входные данные Представление выходных данных
вар.
12 2 числа int. Вывести число, Вывести 30, остальные отбросить
наибольшее по модулю
13 2 числа usignedint. Выве­ Каждые 20 символов выполнять перенос
сти большее из чисел строки
14 4 числа float. Вывести Вывести числа, больше чем А
меньшее из чисел
15 2 числа double. Операция После каждой цифры 9 выполнять верти­
деления кальную табуляцию
8. ПОРАЗРЯДНАЯ ОБРАБОТКА ДАННЫ Х

Кроме арифметических операций в языке C++ допускается выпол­


нять поразрядные логические операции. Поразрядными они называются
потому, что реализуются над соответствующими двоичными разрядами
независимо.
В табл. 20 показан пример программного кода выполнения логиче­
ского И и ИЛИ над целыми числами.
Таблица 20
Поразрядные операции над числами
int N,M,R; Name Value
N=16; /*0x0010;*/ N 16
M=15;/*0x000f;*/ M 15
R=N&M; R 0
int N,M,R; Name Value
N=16; /*0x0010;*/ N 16
M=15; /*0x000f;*/ M 15
R=N|M; R 31

Поразрядные операции применяют для реализации алгоритмов


«низкого» уровня. Например, для управления оборудованием либо обмена
информацией по последовательным каналам связи. Чаще всего в подобных
алгоритмах необходимо выделить содержимое определенных групп заря­
дов и установить их в нужное значение.
Операция логического И используется для маскирования отдельных
разрядов, т е. в выделении содержимого нужного набора разрядов.
Маска - двоичное число, которое содержит единицы в позициях вы­
деляемых разрядов. В табл. 21 показано, как программно выполнить мас­
кирование разрядов. Комментарий содержит шестнадцатеричное представ­
ление значений переменных.
Таблица 21
Маскирование разрядов
int N,M,R; Name Value
N=2226; /*0x08b2;*/ N 226
M=48; /*0x0030;*/ M 48
R=N&M; R 48

46
8. Поразрядная обработка данных

После логического умножения на маску образуется результат. Срав­


нивая его с заранее рассчитанными величинами, реализуют программную
логику выработки результата.
Операции сдвига разрядов применяются для анализа и преобразова­
ния отдельных групп разрядов. С арифметической точки зрения сдвиг
вправо равносилен делению на 2, а сдвиг влево - умножению числа на 2.
В табл. 22 показано, как полученный маскированием результат мо­
жет сдвигаться вправо.
Таблица 22
Сдвиг разрядов
int N,M,R; Name Value
N =2226; /*0x08b2;*/ N 226
M =48; /*0x0030;*/ M 48
R=N&M; R 3
R =R »4;

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


табл. 21 и 22, видно, что сдвиг на 4 разряда вправо эквивалентен делению
на 16. Проведение подобных аналогий полезно при программировании ал­
горитмов поразрядной обработки.
В табл. 23 приведен пример программного кода шифрования и де­
шифрования строки символов.
В первом примере результатом выполнения программы будет за­
шифрованный код. В примере 2 получим уже дешифрованную строку.

Таблица 23
Пример шифрования и дешифрования
char Str[]=" Совершенно секретно!!!";
char Key []=ncafkgfkghagkaglgkgkj gl 1hrktu";
char Res [100];
in t;
//кодирование
for(int i=0; i<sizeof(Str)/sizeof(char);i++0
Res[i]=Str[i]AKey[i];
char Str[]=" Совершенно секретно!!!";
char Key []=ncafkgfkghagkaglgkgkj gl 1hrktu";
_______char Res [100];_____________________________________________

47
8. Поразрядная обработка данных

Окончание табл. 23
in t;
//кодирование
for(int і=0; i<sizeof(Str)/sizeof(char);i++0
Res[i]=Str[i] AKey [i];
// декодирование
for(int i=0; i<sizeof(Str)/sizeof(ehar);i++0
Res[i]=Res[i]AKey[i];

Шифрование основано на использовании поразрядной операции


суммирования по модулю 2. Для шифрования на исходную строку «накла­
дывается» случайная последовательность символов. Наложение последо­
вательности - это поразрядное суммирование. Если на зашифрованную
строку наложить ту же случайную последовательность, выполнится де­
шифрование (табл. 23).

8.1. Шифрование матриц

В примере в табл. 24 к каждому элементу добавляется ключ, а на его


место записывает остаток от деления суммы ключа и значения элемента
на 10. Таким образом получается зашифрованная матрица.
Таблица 24
Пример шифрования и дешифрования матрицы
int key; //ключ
int array [N]; // массив
for(int i = 0; i < N; i++) // цикл шифрования
{
arrayfi] = ((array [i] + k e y ) % 10);
_______ 1_________________________________________________________
for (int i = 0; i < N; i++) // цикл расшифровки
{
arrayfi] = (((array[i] +10) - key) % 10);
_______ 1_________________________________________________________
Для расшифровки к элементу прибавляется 10 (чтобы исключить от­
рицательные значения), вычитается ключ и записывается остаток от деле­
ния на 10. Алфавит для данного примера - цифры.
48
8.2. Шифр Бернама

8.2. Шифр Вернама

Шифр является разновидностью криптосистемы одноразовых блок­


нотов.
Таблица 25
Пример шифрования Вернама
void shifr_Vemam
{
int іДеп; //Определяем необходимые переменные
len = strlen("Holo word!");// определяем длину строки открытого
текста
char *oStr = new char[len]; //объявляем динамический массив ука­
занной длины для открытого текста
char *key = new char[len]; //точно такой же массив объявляем для
ключа
char *shStr = new char[len]; //массив-приемник для зашифрован­
ного текста
oStr="Hello.\, word!"; //помещаем в массив открытый текст
// определяем ключ случайным образом
for(i = 0; i < len; i++)
key [i]=(char)rand()%255;
//собственно само шифрование
for(i = 0; i < len; i++)
shStr[i]=oStr[i]Akey [i];
//для наглядности выведем на экран результат работы
printf("\nOtkrytyi text: %s", oStr);
printf("\nZashifrovanyi text: %s", shStr);
i ________________________________________________________________
9. УКАЗАТЕЛИ

Указатель - производный тип, позволяющий хранить адреса памяти,


в которых размещена переменная. Указатель имеет тип, тип указателя
определяется соответственно синтаксису языка C++.
Например, выражение char *РМ объявляет указатель, здесь РМ -
указатель символьного типа. Он может хранить только адреса символов, но
не сами символы.
Поскольку символьные массивы, как и любые другие массивы, раз­
мещаются в памяти последовательно, обращаться к массиву можно по ад­
ресу его первого элемента, т.е. по указателю. Чтобы указатель принял зна­
чение адреса переменной, используется операция разыменования &.
Например, выражение

РМ = &М[0];

означает, что указатель РМ получает адрес нулевого элемента мас­


сива. Выражение

*РМ=’А ’;

означает, что в память по адресу из РМ будет записано значение сим­


вола А. Операция * перед именем указателя означает операцию над содер­
жимым памяти, на которую указывает указатель.
Над значениями указателя допустимы операции целочисленной
арифметики. Программный код в табл. 26 иллюстрирует основные возмож­
ности по изменению значений переменных через указатель. Справа пока­
зана информация отладчика: 32-разрядный адрес массива и значения его
элементов после выполнения программного кода.
Важно подчеркнуть, что тип указателя определяется независимо и,
по сути, создает возможность различной интерпретации содержимого па­
мяти. В табл. 27 приведен пример того, как указатель на целочисленный
массив может быть преобразован в символьный тип. После этого преобра­
зования с областью памяти, содержащей два 16-разрядных целых, опери­
руют как с последовательностью четырех однобайтовых символов.

50
9. Указатели

Таблица 26
Модификация значений массива по указателю
int intArray[2];
intArray[0]=9;
intArray[l]=99;
int *plnt;
pInt=&intArray [0];
*plnt=*plnt +1;
*(plnt+ 1) = *(plnt+ 1 ) + 1;
intArray 0x0012ffl8 int [2]
[0] 10 int
rn loo int
Таблица 27
Преобразование типа указателя
int intArray [2];
intArray[0]=9;
intArray[l]=99;
int *plnt;
pInt=&intArray [0];
char *pChar;
pChar = (char *) pint;
char cl, c2, c3, c4;
cl = *pChar;
c2 = (*pChar+l);
c3 = (*pChar+2);
c4= (*pChar +3);___________________________________________

Практическое задание 4. Поразрядная обработка данных


Задание', выполнить расчеты поразрядно.
Таблица 28
Варианты для практического задания 4
№ Представление
Входные данные
вар. выходных данных
i Выполнить конъюнкцию 3 чисел У результата поменять знак
2 Выполнить сдвиг вправо на п разря­ Обнулить п-й бит
дов
3 Выполнить дизъюнкцию 3 чисел Вывести п-й бит числа

51
9. Указатели

Окончание табл. 28
№ Представление
Входные данные
вар. выходных данных
4 Умножить результат на п-ю сте­
пень числа 2
5 Выполнить исключающее ИЛИ У результата поменять знак
6 Определить положение старшей Заменить стоящую справа 1 на 0
единицы в длинном целом числе N
7 Выполнить сдвиг влево на Зраз- Обнулить п-й бит
ряда
8 Выполнить инверсию целого Результат округлить до следую­
числа щей степени числа 2
9 Выполнить конъюнкцию 2 чисел.
Заменить стоящий справа 0 на 1
10 Определить положение старшего Вывести п-й бит числа
нуля в длинном целом числе N
11 Выполнить инверсию целого Умножить результат на п-ю сте­
числа пень числа 2
12 Выполнить дизъюнкцию2 чисел Обнулить п-й бит
13 Выполнить сдвиг вправо на 2 раз­ Заменить стоящую справа 1 на 0
ряда
14 Выполнить сдвиг влево на У результата поменять знак
празрядов
15 Выполнить исключающее ИЛИ Вывести п-й бит числа
10. СИМВОЛЬНЫЕ МАССИВЫ И СТРОКИ

Символьные массивы в языке C++ создаются и обрабатываются


двумя способами:
1. традиционным образом: операция над массивом осуществляется как
операция над отдельными элементами соответственно объявленному типу;
2. нетрадиционным образом: обработка символьного массива реализу­
ется как обработка строки. Строкой считается последовательность символов
переменной длины. Для этого в массиве должен присутствовать символ
ограничителя строки. Код символа ограничителя равен 0, поэтому его назы­
вают нулевым символом. Этот символ программист может разместить в лю­
бом месте массива, т.е. при одной и той же длине массива соответствующая
ему строка может иметь различную длину.
Ответственность за наличие нулевого символа и корректность обра­
ботки возлагается на программиста. В табл. 29 приведен программный код,
иллюстрирующий размещение символьного массива и строки в памяти.
В окне отладчика можно увидеть, что объявленная строка символов содер­
жит нулевой символ-ограничитель.
При обработке строк часто используют указатели.
Таблица 29
Строка и символьный массив в памяти
mt _tmam(mt arge, _TCHAR* argv[])
!
char СЬагАггау[]=”Строка символов”;
char сArray [50]:

return 0;
J______
Nam e V a lu e
® у с А гга ѵ 0 x 0 0 1 2 f f 1C "ММММММММММММММММММММСтроК* СИ М ВО ЛО В'

(Э у C h a rA rr a y 0 x 0 0 1 2 ff3 0 ’ С т р о к а си м в о л о в ’

Рис. 9. С грока и символьный массив в памяти

Стандартная библиотека C++ включает набор строковых функций,


которые позволяют: копировать строки, объединять две строки в одну, а
также сравнивать пары строк между собой (табл. 30). Существуют функции
53
10. Символьные массивы и строки

sscanf и sprintf аналогичные функциям ввода/вывода с консоли. Чтение и за­


пись данных они выполняют в символьные строки.
Таблица 30
Функции обработки строк
char *strcpy( char *strDestination, const char *strSource);
char *strcpy( char *strDestination, const char *strSource);
int strcmp( const char *stringl, const char *string2 );
int sscanf( const char *buffer, const char *format [, argument] ...);
int sprint! char *buffer, const char *tbrmat [, ardument] ... ):_____
Функции работы со строками обеспечивают безопасную обработку
строк. Им следует отдавать предпочтение перед использованием циклов.
Одна из частых ошибок обработки строк - выход за границу массива.
Это иллюстрируется рис. 10. Строковая функция strepy копирует строку
большего размера.
Таблица 31
Пример копирования за пределы массива
char CharArray []=”Строка символов”;
char cArray[10J;
strepy (сArray, CharArray);
_______return 0;________________________________________

Pnc. 10. 1Гример копирования за пределы массива

Память программы оказывается некорректно измененной, что застав­


ляет ее завершиться аварийно с помощью исключения. Сообщение об ис­
ключении показано ниже программного кода.
Соблюдение границ выделенной памяти не вызывает исключения
(см. табл. 32).
54
10. Символьные* массивы и строки

Таблица 32
Пример корректного копирования
char CharArray []=”Строка символов”;
char с Л rr ay [ 10];
strcpy(cArray, & CharArray [7]);
return 0;
Name Value
6) cArray 0x00i2ffic 'oweonoe'
6) * CharArray 0x00i2ff30 'Строка oweonoe'

Практическое задание 5. Сравнение строк


Задание: разработать программу, позволяющую проводить сравнение
данных, введенных с клавиатуры, и выводить на экран результат сравнения
в соответствии с вариантом.
Сравнить строку п со строкой п+5. где п - номер варианта по
списку (для п > 15 продолжить считать с начала списка), вывести резуль­
тат сравнения.
Таблица 33
Варианты для практического задания 5

Входные данные Представление выходных да......
вар.
i 20 символов. Результат с учетом Выполнить побайтное копирование
регистра символов из строки п+5 в строку п
2 25 телефонных номеров в фор­ Выполнить побайтное копирование и
мате ХХХХХХХХХХХ. Резуль­ символов из строки п в строку п+5 в
тат без учета регистра случае несовпадения
3 25 символов. Результат с уче­ Объединить п символов
том регистра строки ii ■5 со строкой ii. Результат
сохранить в строкеп
4 10 наименований учебных кур­ Выполнить побайтное копирование
сов. Результат без учета реги­ символов из строки п+5 в сіроку п в
стра случае несовпадения.
5 15 телефонных номеров в фор­ Объединить ii символов
мате ХХХХХХХХХХХ. Резуль­ строки п+5 со строкой п. Результат
тат с учетом регистра сохранить в строкеп
6 15 дат в формате дц. мм. гг. Ре­ Выполнить побайтное копирование п
зультат с учетом регистра символов из строки п-5 в строку п в
случае несовпадения

55
10. Символьные массивы и строки

Окончание табл. 33

Входные данные Представление выходных данных
вар.
7 20 символов. Результат без Выполнить побайтное копирование
учета регистра символов из строки n+5 в строку n в
случае несовпадения
8 10 фамилий. Результат с учетом Объединить n символов
регистра строки n+5 со строкой n. Результат
сохранить в строке n
9 25 дат в формате дд. мм. гг. Ре­ Выполнить побайтное копирование
зультат без учета регистра n+5 символов из строки nв
строку n+5 в случае несовпадения
10 15 фамилий. Результат с учетом Выполнить побайтное копирование
регистра символов из строки n+5 в строку n в
случае несовпадения
11 30 символов. Результат без Выполнить побайтное копирование n
учета регистра. символов из строки n в строку n+5 в
случае несовпадения
12 10 дат в формате дд. мм. гг. Ре­ Объединить n+5 символов
зультат без учета регистра строки n+5 со строкой n. Результат
сохранить в строке n
13 10 фамилий. Результат с учетом Выполнить побайтное копирование
регистра. символов из строки n+5 в строку n в
случае несовпадения
14 20 дат в формате дд. мм. гг. Ре­ Объединить n символов
зультат без учета регистра строки n+5 со строкой n. Результат
сохранить в строке n
15 15 фамилий. Результат с учетом Выполнить побайтное копирование n
регистра символов из строки n+5 в строку n в
случае несовпадения
11. ПЕРЕДАЧА ПАРАМЕТРОВ ФУНКЦИЯМ

В C++ существует 3 способа передачи параметров в функцию:


1. Передача параметра по значению (Call-Ву-Value). При передаче по
значению в точке вызова функции копируются значения фактических пара­
метров. Все преобразования внутри функции выполняются над копиями, не
изменяя при этом оригиналы. При передаче по указателю (ссылке), в точке
вызова передается указатель на фактические параметры. Все преобразования
в функциях могут изменять оригиналы. Таким образом, если требуется изме­
нить некоторую переменную за счёт вызова функции, следует использовать
указатель. В этом случае изменение значений параметров в теле функции не
изменит значений, которые передавались в функцию извне (при ее вызове).
2. Передача параметра по адресу переменной. В этом случае функции
в качестве параметров передаются не копии переменных, а копии адресов
переменных, то есть указатель на переменную. Используя этот указатель,
функция осуществляет доступ к нужным ячейкам памяти, где расположена
передаваемая переменная, и может изменять ее значение.
3. Передача параметра по ссылке (Call-Ву-Reference). Передается
ссылка (указатель) на объект (переменную), что позволяет синтаксически
использовать эту ссылку как указатель, и как значение. Изменения, внесен­
ные в параметр, который передается по ссылке, изменяют исходную копию
параметра вызывающей функции.
В табл. 34 приведен пример программного кода, в котором вызыва­
емой функции передаются параметры по значению. В окне отладчика
можно видеть, что исходные переменные не изменили своих значений по­
сле вызова функции.
Таблица 34
Передача параметров по значению
void FunctiопА (float х, float у, float z)
{
z = sqrt( x + y );
x = 5;
y = i;
}
int _tmain(int argc, _TCHAR* argv[]0
i____________________________________________________________
57
11. Передача параметров функциям

В табл. 35 параметры передаются по указателю. Как видно из отлад­


чика, исходные значения переменных изменились. Заметим, что данный
пример иллюстрирует механизм перегрузки функций: если объявлены функ­
ции с одинаковыми именами, то при компиляции выбирается та, типы аргу­
ментов которой соответствуют строке вызова. В данном случае это функция
с параметрами-указателями.
Таблица 35
Передача параметров по указателю
void FunctionA (float х, float у, float *z)
{
z = sqrt( x + y );
x = 5;
y = i;
}
void FuncA (float *x, float *y, float z)
{
*z = sqrt( *x + *y );
*x = 5;
*y = 1;
}
int _tmain(int argc, _TCFLAR* argv[]0
{
float x, y, z;
x = 2;
______ _________________________________________________________
58
11. Передача параметров функциям

Окончание табл. 35
z = 10;
FuncA( &х, &у, &z );

return 0;
}
паше value
X 5.0000000
У 1.0000000
Z 2.8284271
Таблица 36

Во многих языках программирования используются ссылки на перемен­


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

59
11. Передача параметров функциям

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


ссылок можно получить результат, аналогичный использованию указателей.
Таблица 37
Передача массива
void ArrayFunc ( int *А, int N)
{
for (int i=0 ; i < N ; i++)
*A++ = *A - i;
}
int _tmain(int argc, TCHAR* argv[])
{
int SomeArray[]= {1,2,3,4,5,6,7,8,9,10};
ArrayFunc( & SomeArrayfO], sizeof( SomeArray) / sizeof(int));
return 0;
_______ 1_________________________________________________________
Name Value
В ф SomeArray 0x0012fFlc
- 0 [о] 1
— 0 [i] 1
- ои 1
- Ф [3] 1
- Ф И] 1
- 0 [5] 1
- Ф И 1
- 0 И 1
• [8] 1
ф [9] 1

Рис. 11. Передача массива

Для обработки в функции массивов необходимо передавать указатель


на массив. Программный код в функции строится исходя из этого требования,
т е. к элементам массива обращаются по указателю. В табл. 37 приведен при­
мер функции, получающей указатель на целочисленный массив.
При обработке массива внутри функции для перехода от одних эле­
ментов массива к следующим, используют операцию увеличения указа­
теля ++. Увеличение на 1 указателя изменяет адрес на то число байт, которое
соответствует типу указателя. Например, если указатель целого типа, а це­
лые числа 32-разрядные, то адрес будет увеличен на 4 байта. При програм­
мировании учитывать разрядность не следует. Это делается автоматически
соответственно типу указателя.
12. СТРУКТУРЫ И ОБЪЕДИНЕНИЯ

Структуры представляют собой сложный тип данных. В отличие от


массивов, переменная структурного типа может включать в себя данные раз­
личных типов. Из структуры переменных, в свою очередь, могут строиться
массивы и структуры, которые их используют как простые типы. Структуры
объявляются с помощью ключевого слова struct. В табл.38 приведен пример
программного кода, использующего структурную переменную.
Таблица 38
Использование структурной переменной
int _tmain(int argc, TCHAR* argv[])
{
struct Student {
char Name[100];
char Group [100];
int Age;
};

Student x;
strcpy(&x.Name[0],’’Иванов Иван Иванович”);
strcpy(&x. Group [0],”KT6ol -1”);
x.Age = 18;

return 0;
}______________________________________________________

1 Name Value
3 0 X {Name =0x0012fe74 Иванов И.И.* Group =0x0012fed8 Н-999* Аде=20 }
—0 0 Name 0x0012fe74 Иванов И.И."
—0 0 Group 0x0012fed8 H-999'
— у Аде 20

Рис. 12. Использование структурной переменной

Использование структурных переменных дает возможность прибли­


зить абстракции программ к понятиям предметной области. Например, мани­
пулирование переменной типа student в примере в табл. 38 во многих случаях
61
12. Структуры и объединения

не требует знания её внутренней структуры при выполнении копирования, пе­


редачи функции, включения в более сложные структуры данных.
При использовании указателей на структуры к элементам обраща­
ются не через точку (.), а через стрелку ( -> ). В табл. 39 показан пример
обращения к полям структуры по указателю.
Объединения (union) также относятся к сложным типам данных. Объ­
единения позволяют включать в себя разнотипные данные, но, в отличие от
структуры, для каждого простого типа память не выделяется. По сути одно
и то же значение представляется данными разного типа.
Таблица 39
Указатель на структурную переменную
int _tmain(int argc, _TCHAR* argv[])
{
struct Student {
char Name[100];
char Group [100];
int Age;
};

Student x;
strcpy(&x.Name[0],’’Иванов Иван Иванович”);
strcpy(&x.Group[0],”K T6ol-Г’);
x.Age =18;
Student *pSt;
pSt =&x;
pSt->Age = pSt->Age+5;
return 0;
}_______________________________________________________
Name Value
Е # I {Name =0x0012fe74 "Иванов И.И." Group =0x00 12fed8 ТЛ-999" Аде=25 }
—0 у Name 0x0012fe74 "Иванов И.И."
—Щ у Group 0x0012fed8 31-999'
^ Аде 25

Рис. 13. Указатель на структурную переменную

Объединения используют для хранения значений в разнотипном


представлении.

62
12. Структуры и объединения

Практическое задание 6. Структуры


Задание: Использовать структуру-переменную
Создать два массива структур о студентах 2-х групп. О каждом
студенте записать: фамилию, имя, отчество, год рождения, группу, оценки
по пяти экзаменам.
Таблица 40
Варианты для практического задания 6
№ Представление
Входные данные
вар. выходных данных
i Сортировка по баллам Определить средний балл за
дисциплину
2 Сортировка по фамилиям Определить количество одно­
фамильцев
3 Сортировка по фамилиям. Определить,
в какой группе больше студентов
4 Определить, в какой группе средний Сортировка по фамилиям
возраст студентов ниже
5 Определить, какая дисциплина сложнее Сортировка по баллам
6 Определить, какие студенты останутся Сортировка по баллам
на пересдачу
7 Определить, в какой группе средний Сортировка по фамилиям
возраст студентов выше
8 Вывести возраст старшего студента Сортировка по фамилиям
9 Вывести возраст младшего студента Сортировка по году рождения
10 Определить список лучших студентов Сортировка по баллам
(набравших максимальный балл)
11 Вывести 10 лучших студентов (по мак­ Сортировка по баллам
симальному баллу)
12 Определить группу, в которой сту­ Сортировка по баллам
денты лучше учатся (средний балл)
13 Определить, в какой группе учится Сортировка по фамилиям
младший студент
14 Определить, в какой группе все сту­ Сортировка по баллам
денты успешно сдали сессию
15 Определить, какая дисциплина оказа­ Сортировка по баллам
лась легче для студентов

63
13. КЛАССЫ

Основное достоинство использования классов проявляется при реше­


нии сложных задач, и состоит в повышении качества программного про­
дукта. Классы дают возможность скрывать детали программирования, повы­
шать уровень абстракций прикладной задачи, более естественным и понят­
ным образом строить программный код.
Таблица 41
Использование объединения
union PinCode {
char sPin[4];
int iPin;
short shPin[2];
lont int IPin;
};
PinCode y;
y.iPin=129124;
return 0;
_______ 1_______________________________________________________

N am e Value
Е3 0 у {sPin =0x0012fe5c "dm " iPin=129124 shPin=0x0012fe5c ...}
— с-3 0 sPin OxOOlZfieSc^m *
— о га 100 'd'
■ в и -8 'іи'
■ q га I 'm '
■ 0 га 0
— V ІРІп 129124
в t shPin 0x0012fe5c
■ о га -1948
L 0 га 1
1
— У ІРІП 129124

Рис. 14. Использование объединения

Знание принципов организации классов необходимо при использова­


нии стандартной библиотеки C++, которая организована в объектном стиле.
Использование классов при программировании представляет собой особый
стиль программирования - объектное программирование.

64
13. Классы

Класс - это сложная стру кту ра данных, которая включает в себя свой­
ства и методы. Свойства класса - это любые типы данных. Методы - это
функции, выполняющие обработку данных. Аналогичным образом функции
можно включать в структуры (struct). Основным отличием класса является
то, что в классах имеется возможность ограничить доступ к элементам
класса (ключевые слова public, private, protected).
Ключевое слово public определяет элементы, доступные пользовате­
лям класса. Пользователь класса - это программный код, создающий и ис­
пользующий объекты данного класса.
Всякий объект является экземпляром данных, созданных по описа­
нию класса. Описание играет роль матрицы.
Ключевое слово private определяет закрытые свойства и методы. Эти
свойства и методы недоступны внешним пользователям, однако доступны
любым методам класса.
Ключевое слово protected определяет свойства и методы, закрытые
от внешних пользователей, но доступные в классах, связанных с данным
классом отношением наследования.
Закрытые данные класса размещаются после модификатора доступа
private. Если отсутствует модификатор public, то все функции и переменные
по умолчанию являются закрытыми (как в первом примере).
Обычно, приватными делают свойства класса, а публичными - его
методы.
Напрямую обращаться к закрытым данным класса нельзя. Для работы
с этими данными используют методы этого класса.
Таблица 42
Пример работы с классами
class Sport {
public:
// Установка среднего значения очков
void set_average_score(float score)
{
average_score = score;
}
// Получение среднего значения очков
float get average score (_________________________________

65
13. Классы

Окончание табл. 42
“1
return average_ score;
}
std::string name;
std: :string last_name;
int scores[5];
private:
float average_ score;

В примере выше используется функция get_average_score() для по­


лучения среднего значения очков, набранных спортсменом за этап, и
set_average_score() для выставления этих очков.
Функция set_average_score() принимает средний результат в качестве
параметра и присваивает его значение закрытой переменной average_score.
Функция get_average_score() просто возвращает значение этой переменной.
Любое описание класса состоит из двух частей: интерфейса и реали­
зации.
Интерфейс - это перечисление типов и имен свойств, а также сигна­
тур методов. Реализация класса - это программный код методов класса.
В табл. 43 показан программный код, иллюстрирующий использова­
ние классов. Класс Students включает в себя ряд свойств и методов, целост­
ным образом описывающие сущность «Студенты». Заметим, что свойством
класса могут быть сложные структуры данных. Например, структура Stu-
dentFields позволяет хранить информацию об имени, номере группы и воз­
расте студента.
Таблица 43
Интерфейс класса Students
class Students {
public:
Students();
bool AddStudent(string Name, string Group, int Age)
StudentField GetInfo(int Num);
private:
StudentField StudTablc|20];_____________________

66
13. Классы

Окончание табл. 43
int TableCount;

protected:
int MaxAge;
int MinAge;
};
struct StudentField{
string Name;
string Group;
int Age;
};___________________________________________________________
Среди методов класса Students можно заметить одноименный метод
Students(). Этот метод называют конструктором класса. Он выполняет все
действия, необходимые при создании экземпляра объекта. Такие действия
будут выполнены в точке нахождения в программном коде строки

Students X;
где X - имя переменной-экземпляра класса. В табл. 44 показана реализация
класса, в которой метод «конструктор» инициализирует свойства класса
TablCount, MaxAge, MinAge нулевым значением.
Таблица 44
Реализация класса Students
Students::Students()
{
TableCount = 0;
MaxAge = 0;
MinAge = 100;
}
bool Students::AddStudent(string Name, string Gropu, int Age)
{
if (T ableCount <20)
{
StudTable[TableCount].Name = Name;
StudTable[TableCount].Group = Group;
StudTable[TableCount].Age = Age;
TableCount++;
_______MaxAge = max(Age,MaxAge);_________________________________
67
13. Классы

Окончание табл. 44
MinAge = min(Age,MinAge);
return true;
}
return false;
}
StudentField Students: :GetInfo(int Num)
{
return StudTable[Num];
}______________________________________________________
Хорошим стилем построения классов считается максимальное
скрытие (инкапсуляция) свойств и предоставление доступа к ним через
методы. Такой прием значительно повышает безопасность использова­
ния объектов: если свойства открыты, пользовательский код способен
любым образом изменить их значения. Последствия такого неконтроли­
руемого изменения состояния объекта непредсказуемы. Если же значе­
ния свойств модифицируются методом класса, состояние объекта нахо­
дится под контролем.

Таблица 45
Пример использования класса Students
int _tmain(int argc, _TCHAR* argv[])
{
Students Stud Group;
bool result;
StudGroup. AddStudent(“neTpOB П.П.”,”КТбо 1-1”, 17);
StudGroup.AddStudent(“HaHOB И.И.”,”КТсо1-2”,17);
StudGroup.AddStudent(“CimopoB C.C.”,”KT6ol-3”,17);

StudentField Any Student;


AnyStudent = StudGroup.GetInfo(2);
return 0;
i _________________________________________________________
В коде в табл. 45 можно видеть, что массив StudTable из 20 элементов
недоступен внешнему пользователю напрямую. Для добавления нового эле­
мента следует воспользоваться методом AddStudentf), который отслежи­
вает количество элементов.

68
13. Классы

Если количество элементов превышает 20, добавление не произво­


дится, а возвращается значение false.
S t u d e n t F l e l d A n y S ty d e n t;
A n y S ty d e n t = S tu d G ro u p . |
r e tu r n 0;
} vi AddStudent
V Getlnfo
S t u d e n t s ::S t u d e n t s (}
У MaxAge
У MinAge
T a b le C o u n t = 0;
StudTable
M axA ge - 0 ;
TableCount
M in A g e = 1 0 0 ;

Рис. 15. Подсказка MS Visual Studio

Программный код на рис. 15 иллюстрирует использование объект­


ного стиля программирования. Основа объектного стиля - создание экзем­
пляров классов и манипулирование свойствами и методами классов.
Среда программирования MS Visual Studio оказывает поддержку в
программировании на основе использования классов. На рис. 15 показан
пример того, как система интеллектуальной подсказки при наборе на клави­
атуре имени объекта строит окно с перечислением свойств и методов класса
Students. Таким образом, уже на этапе создания программного кода пред­
принимаются меры по снижению возможности появления ошибки.
Отметим также, что структура выводимой отладчиком информации со­
ответствует структуре класса. На рис. 16 приведен соответствующий пример.
Name Value
в ^ StudGroup {StudTable=0x0012fe5cTableCount=3MaxAge=18 ...}
0xQ012fe5c {Name="Иванов И.И.' Group=11-999' Age=17}
£
_Lj

—Е
иг~>
>

- и # [0] {№те="ИваноБ И,ИЛGroup="H-999' Age=17 }


-ш 0 [1] {Name="Петров П.ИЛGroup="H-888" Age=17 }
Чв $ т {Name="Сидоров И,И.гСгоир=’У1-777тAge=18 }
- ф TableCount 3
- ф MaxAge 18
— ф MinAge 17
П у AnyStydent {Name="Сидоров И,ИЛСпхір="И-777" Age=18 }
—(+1 у Name "Сидоров И.ИЛ
—0 Group "И-777'
— У Аде 18

Рис. 16. Экземпляр класса Students в отладчике

69
13. Классы

Практическое задание 7. Таблицы


Задание ', вывести данные о спортсменах в консольном приложении в
виде таблицы (фамилия, год рождения, рост, результат забега на 1 км в ми­
нутах, результат забега на 3 км в минутах).
В нечетных вариантах 1, 3, 5 и т.д. использовать функции из заголов­
ков <iomanip>. В четных вариантах 2 ,4 ,6 и т.д. использовать класс для отоб­
ражения таблицы.
Таблица 46
Варианты для практического задания 7

Входные данные
вар.
i Упорядочить фамилии по возрастанию
2 Упорядочить рост по убыванию
3 Найти лучший результат (1 км)
4 Найти худший результат (3 км).
Выразить в секундах
5 Перевести результаты забега на 1 км в секунды
6 Вывести данные только по спортсменам среднего роста (до 170 см)
7 Вывести данные только по спортсменам с ростом выше среднего
8 Вывести общий средний результат по забегу на 3 км
9 Вывести лучший средний результат (1 км) и фамилию спортсмена
10 Упорядочить фамилии по убыванию
11 Вывести результаты спортсменов по году рождения (год вводится в диа­
логе)
12 Вывести результат выбранного спортсмена (фамилия вводится в диалоге)
13 Вывести низший средний балл (на 3 км)
Выразить в миллисекундах
14 Вывести только результаты спортсменов на определенную букву (вводится
в диалоге)
15 Упорядочить результаты забега на 3 км по убыванию
14. ВВОД И ВЫВОД
ИНФОРМАЦИИ В ФАЙЛЫ

Файл - структура данных для хранения информации на устройствах


долговременного хранения.
Все функции по обслуживанию файлов возлагаются на операционную
систему. Чтобы выполнить чтение или запись данных из файла, прикладная
программа должна реализовать следующие действия:
1. Открыть файл. Операция открытия заключается в том, что со сто­
роны программы операционной системы отправляется запрос, который со­
держит имя файла, дополнительную информацию для доступа и выполнения
операции. Операционная система по этому запросу пытается отыскать файл
и проверяет допустимость выполнения запрошенных действий. Если файл
существует и операции допустимы, то файл считается открытым для при­
кладной программы (о чем она получает сообщение).
2. Если файл открыт, то посредством библиотечных функций чтения и
записи осуществляется обмен информацией с файлом. При записи информа­
ции в общем случае не гарантируется ее мгновенная фиксация в файле на
внешнем устройстве. Обычно записываемые данные сохраняются в промежу­
точных системных буферах. Для явной записи необходимо вызвать соответ­
ствующую функцию сохранения данных на устройство и очистки буфера.
3. После завершения работы с файлом он должен быть закрыт. Соот­
ветствующая функция отправляет запрос операционной системе, по кото­
рому очищаются промежуточные буферы и при необходимости снимаются
блокировки с файлов.
Примерная последовательность действий программы при использова­
нии информации, хранимой в файле, приведена ниже.
1. Открыть входной файл и считать его содержимое в переменные про­
граммы.
2. Закрыть входной файл. Выполнить обработку, подготовить входные
данные.
3. Открыть выходной файл.
4. Записать выходные переменные в файл.
5. Закрыть выходной файл

71
14. Ввод и вывод информации в файлы

Таблица 47
Запись в файл функциями библиотеки С
FILE* f;
F =fopen(“ TextF ile.txt’Y’w”);
If9f==NULL)
printf(“\n File open error ! \n”);
else
{
char Str[]=”CTpoKa”;
int Num=55;
fprintf(f,’’Строка для записи в файл = %s, число = %d”, Str, Num);
fclose(f);
}_________________________________________________________
В библиотеке C++ имеется несколько семейств функций ввода-вы­
вода. В табл. 47 приведен пример программного кода записи данных в файл,
который использует функции стандартной библиотеки языка С. В табл. 48
показан пример чтения данных.
Таблица 48
Чтение из файла функциями библиотеки С
f = fopen(“TextFile.txt”,”r”);
if( f == Null)
printf(“\n File open error ! \n”);
else
{
charStr [100];
int Num;
int res =
fscanf(f,”%s%*s%*s%*s%*s%*s%*s%*s%*s%*s%d”,Str,&Num);
fclose(f);
}_______________________________________________________
Особенностью рассматриваемых библиотечных функций является ис­
пользование форматной строки функциями fprintf и fscanf.
Альтернативным вариантом ввода-вывода в файлы может считаться
набор функций библиотеки C++. Для встроенных типов не требуется фор­
матная строка. Считается, что текст программы становится более понятным
и естественным благодаря использованию операторов ввода-вывода.

72
14. Ввод и вывод информации в файлы_____________________

Таблица 49
Запись в файл функциями библиотеки C++
#include “stadfx.h”
#include <fstream>
#include <iostream>
using namespace std;

int _tmain(int argc, _TCHAR* argv[])


{
fstream OutFile;
( )иіІ і1с.ореп(Ь”Эксперимснтально созданный файл+хГ,
ios_base::out);
OutFile « endl « ’’Строка вывода \n в этот файл”;
OutFile « endl « ’’Еще одна строка” « endl;
OutFile. close();
return 0;
} ___________________________________________

O u t F i l e . o p e n ( " N e w F i le . t x t " . i o s : : o u t
r e tu rn 0 ;
^ openmode -
=T) operator!
operator =
=^j operator void *

^1_____
Lt ] pos_type
precision
=♦ pword □
= * rdbuf
^ rd state 0

Рис. 17. Запись в файл функциями библиотеки C++

На рис. 17 показан пример программного кода записи в файл. Следует


обратить внимание на заголовочные файлы и наличие строки

using namespace std;


которая определяет пространство имен библиотеки C++. Переменная OutFile
является объектом класса fstream. На врезке рис. 17 показана подсказка MS
Visual Studio, облегчающая использование класса fstream.

73
14. Ввод и вывод информации в файлы

Таблица 50
Чтение из файла функциями библиотеки C++
OutFile.орсп(Ъ”Эксперименталыю созданный файл+хГ,
ios_base::in);
char Strl [100],Str2[100];
OutFile» Strl;
OutFile » Str2;

_______return 0;___________________________________________________
В табл. 50 показан пример чтения из файла. При чтении из файла с
помощью оператора » выполняется контроль типа переменной. Это озна­
чает, что считываемые символы преобразуются к значению соответствую­
щему типу переменной. Например, если считывается строка, в нее поме­
щаются последовательно символы до тех пор, пока не будет встречен сим­
вол-разделитель. По умолчанию таковым является пробел, запятая, точка с
запятой, точка.
Обмен данными с файлом осуществляется функциями из библиотек
C++ в основном на уровне встроенных типов C++. Более сложные объекты
для сохранения в файл должны декомпозироваться на простые элементы.
Рассмотрим эту процедуру на примере ввода данных, представляющих со­
бой строки со специальным разделителем. В табл. 51 показаны две строки
текстового файла, причем всякая строка файла имеет три поля, каждое из
которых отделено символом #.
Таблица 51
Строки со специальным разделителем
Петров А.А.#12.12.1991#город Таганрог___________________________________
Сидоров С.Л#01.06.1996#село Несветайское_______________________________

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


массив структурных переменных из 10 элементов. Для этого использованы
методы getline класса fstream.
Все операции чтения и записи в файлах связаны с перемещением аб­
страктного указателя файла. При открытии файла этот указатель помеща­
ется в известную позицию, например, в начало. Любое чтение или запись,
автоматически перемещают указатель в позицию, следующую за последним
обработанным байтом. Это нужно учитывать, если программа считывает или

74
14. Ввод и вывод информации в файлы

записывает информацию в файл с произвольной позиции. Среди файловых


функций имеются функции перемещения указателя.
Перемещение указателя в файле, открытом с помощью класса fstream,
выполняется с использованием метода seekp. Метод включает два параметра:
число со знаком, указывающее на количество позиций смещения (одна пози­
ция - один байт) и константа класса, указывающая на «точку отсчета» смеще­
ния (ios::cnd - относительно конца файла, ios::beg - относительно начала,
ios::cur - относительно текущей позиции). В табл.51 показаны примеры под­
сказки дляустановки нужной константы. Перемещение за пределы файла невоз­
можно, указатель будет установлен соответственно в последней либо в первой
позиции. Признак ошибки при этом не генерируется.
Таблица 52
Ввод строк со специальным разделителем из файла
struct {
char Name[50];
char BDate[15];
char Place [50];
} User[10];
fstream InFile;
InFile.open(L”NewFile.txt”, ios::in);
int count = 0;
while ( ! InFile.eof() && (count < 1 0 ))
{
InFile.getline(User[count],Name,50,’# ’);
InFile.getline(User[count].BDate, 15,’#’);
InFile.getline(User[count],Place,50);
count++;
}
_______ InFile.closeQ;______________________________________________
При обработке текстов, находящихся в файлах, следует учитывать
наличие «невидимых» символов, которые не отображаются пользователю, но
используются при отображении текста на устройствах. Перемещение указа­
теля в файле должно учитывать наличие таких символов (символы формати­
рования имеют коды: OD - перевод строки, ОА - возврат каретки). В табл. 52
показан фрагмент текста с параллельной 16-ричной кодировкой.
Для того чтобы сохранять в файлах объекты произвольных классов,
необходимо организовать запись тех свойств, которые относятся к простым
75
14. Ввод и вывод информации в файлы

типам. Например, чтобы сохранить в файле объект класса string, следует с


помощью метода c_str() получить указатель на строку в стиле C++, т.е. сим­
вольный массив с нулевым ограничителем. Строка такого типа сохраняется
в файле оператором « . Аналогично любая структурная переменная записы­
вается и считывается по отдельным полям.

Рис. 18. Константы направления перемещения указателя файла

00000000: F2 Е5 Ей F1 F2 20 E2 20|Fi| E 0 E9 EB E5 2C 20 0D | те к с т в Файле,


0Ѳ000Ѳ1Ѳ: on EF F 0 E5 Eh ED E0 E7 j ED E 0 F7 E5 ED ED FB E9 j предназначенный
00900020: 20 E b EB FF 20 ЕЕ E1 F 0 j E 0 E1 EE F2 ЕЙ E8 0D 0Й j для обработки

Рис. 19. Символы текста и символы форматирования текста


15. КЛАССЫ СТРОК И СТРОКОВЫХ п о т о к о в

Класс string является одним из типов, которые объявлены в заголовоч­


ном файле string.
String - класс для обработки символьных строк. В отличие от масси­
вов языка Си, в классе присутствует набор методов, облегчающих выполне­
ние операций над массивами и делающих эту обработку более надежной.
Вот некоторые достоинства класса:
• строка способна динамически изменять свою длину;
• строки допускают объединение с использованием оператора сумми­
рования (+);
• в классе имеются методы для поиска символов и фрагментов строк
в различных вариациях условий;
• имеются методы для выделения из строк фрагментов нужной длины
и с требуемой позицией.
Ниже приведен список некоторых полезных методов класса string:
Таблица 53
Методы класса string

• clear Очищает строку от символов

• compare Сравнивает строку с указанной

• empty Возвращает признак того, что строка пуста

• find Ищет заданную подстроку

• insert Вставляет подстроку

• length Возвращает число символов в строке

• replace Заменяет указанные символы другими

• substr Выделяет подстроку

77
15. Классы строк и строковых потоков

Помимо перечисленных выше методов на практике применяют ме­


тоды size(), resize(), append().
Метод size() возращает длину строки. Возвращаемое значение явля­
ется беззнаковым типом (как и во всех случаях, когда функция возращает
значение, равное длине строке или индексу элемента - эти значения беззна­
ковые). Поэтому нужно аккуратно выполнять операцию вычитания из зна­
чения, которое возвращает size(). Например, ошибочной будет запись цикла,
перебирающего все символы строки, кроме последнего, в виде for (int i = 0;
i < S.size() - 1; ++i).
Кроме того, у строк есть метод length(), который также возвращает
длину строки.
Метод resize изменяет длину строки. К примеру, после применения
S. resize(n) новая длина строки становится равна п. При этом строка может
как уменьшиться, так и увеличиться. Если вызвать в виде S.resize(n, с), где
с - символ, то при увеличении длины строки добавляемые символы будут
равны с.
Метод append добавляет в конец строки несколько символов, другую
строку или фрагмент другой строки. Имеет много способов вызова.
• S.append(n, с) - добавляет в конец строки п одинаковых символов,
равных с. п имеет целочисленный тип, с - char.
• S.append(T) - добавляет в конец строки S содержимое строки Т.
Т может быть объектом класса string или С-строкой.
• S.append(T, pos, count) - добавляет в конец строки S символы строки
T, начиная с символа с индексом pos количеством count.
Методы find может быть заменен на следующие частные методы:
• find first of - ищет в данной строке первое появление любого из
символов данной строки str. Возвращается номер этого символа или значе­
ние string: :npos.
Если задано значение pos, то поиск начинается с позиции pos, возра-
щаемое значение будет не меньше, чем pos. Если значение pos не указано, то
считается, что оно равно 0 - поиск осуществляется с начала строки.
S.find_first_of(str, pos = 0) - искать первое вхождение любого символа
строки str начиная с позиции pos. Если pos не задано, то начиная с начала
строки S.
• find last of
78
15.1. Конструкторы строк

Ищет в данной строке последнее появление любого из символов дан­


ной строки str. Способы вызова и возвращаемое значение аналогичны ме­
тоду find_first_of.
• find_first_not_of
Ищет в данной строке первое появление символа, отличного от сим­
волов строки str. Способы вызова и возвращаемое значение аналогичны ме­
тоду find_first_of.
• find_last_not_of
Ищет в данной строке последнее появление символа, отличного от
символов строки str. Способы вызова и возвращаемое значение аналогичны
методу find_first_of.
Строки можно объявлять и одновременно присваивать им значения:
string SI, S2 = "Hello,world";
Строка SI будет пустой, строка S2 будет состоять из 11 символов.

15.1. Конструкторы строк

Строки можно создавать с использованием следующих конструк­


торов:
• stringO- конструктор по умолчанию (без параметров) создает пу­
стую строку.
• string(string & S) -копия строки S
• string(size_t п, char с) - повторение символа с заданное число п раз.
• string(size_t с) - строка из одного символа с.
• string(string & S, size_t start, size_t len) - строка, содержащая не бо­
лее, чем len символов данной строки S, начиная с символа номер start.
Конструкторы можно вызывать явно, например, так:

S + = string^0, 'а');
В этом примере явно вызывается конструктор string для создания
строки, состоящей из 10 символов 'а'.
Неявно конструктор вызывается при объявлении строки с указанием
дополнительных параметров. Например, так:

string S(10, 'a');


79
15. Классы строк и строковых потоков

15.2. Арифметические операторы

Со строками можно выполнять следующие арифметические опера­


ции:
= - присваивание значения;
+= - добавление в конец строки другой строки или символа;
+ - конкатенация двух строк, конкатенация строки и символа;
==, != - посимвольное сравнение;
<, >, <=, >= - лексикографическое сравнение.
То есть можно скопировать содержимое одной строки в другую при по­
мощи операции SI = S2, сравнить две строки на равенство при помощи
SI = S2, сравнить строки в лексикографическом порядке при помощи SI < S2,
или сделать сложение (конкатенацию) двух строк в виде S = SI + S2.
Для ввода-вывода строк в файл допускается использовать операторы
» и « . В табл. 54 показан пример программного кода.
Полезным для программирования может оказаться использование
строковых потоков. Обработка строковых потоков совершенно аналогична
обработке файловых потоков. Использование привычного синтаксиса и
освоенных обобщений, и соглашений дает возможность более эффективного
программирования.
Таблица 54
Вывод объекта string в файл
string s;
s=” String text “;
fstream outFile;
outFile.open(“TextOut.txt”,ios_base::out);
if(!outFile.bad())
{
outFile « s;
}
outFile.closeQ;__________________________
В табл. 55 приведен программный код, формирующий строку даты
через использование класса строкового потока.
Для использования функциональности класса строкового потока
stringstream необходимо включить соответствующий заголовочный файл
(табл. 55).
80
15.3. Потоки ввода (istream)

Таблица 55
Пример использования строкового потока
#include “stadfx.h”
#include <sstream>
#include <iostream>
#include (string>

using namespace std;


int_tmain(int argc, TCHAR* argv[])
{
stringstream WorkString;
WorkString « 25 « « 10 « « « 2020;

return 0;
}_________________________________________________
Строки и строковые потоки являются ярким примером абстрагирова­
ния близких, но не эквивалентных сущностей. Включая строки как свойства,
объекты строковых потоков обладают совсем не характерным поведением
для строк. Строку класса string можно получить из строкового потока, ис­
пользуя метод str (табл. 55).
Из строкового потока могут считываться данные подобно тому, как
это делалось для файлового потока. На рис. 20 приведен пример, в котором
из строкового потока считываются числа, символы и строка.
s t r i n g s t r e a m W o rk S trin g ;
W o rk S tr in g « 25 « « 10 « " ." « 2010;
s trin g s;
W. = W o r k S t r i n g . s t r (> ;
I П 0 # ! S ' '25.10.2010'
>

Рис. 20. Получение строки из строкового потока

15.3. Потоки ввода (istream)

Для ввода используется оператор » . Он также определен для всех


встроенных типов и некоторых классов стандартной библиотеки.
Оператор » также можно определить для своих классов:

81
15. Классы строк и строковых потоков

istream& operator»(istream & s)


{

}
Некоторые методы класса istream:
• get() - считать следующий символ;
• get(char *buf, streamsize n) - считать максимум n-1 символ и поме­
стить в массив buf;
• get(char *buf, streamsize n, char delim) - считывание символов до сим­
вола-разделителя delim (разделитель не считывается и остается в потоке);
• getline(char *buf, streamsize n);
• getline(char *buf, streamsize n, char delim);
• peek() - считывает следующий символ, но оставляет его в потоке;
• ignore(streamsize n = 1, int delim = EOF) - извлекает символы из потока
до тех пор, пока их число меньше n или пока не встретился символ delim;
• putback(char с) - добавляет символ с в текущую позицию потока;
• unget() - возвращает последний считанный символ в поток.

Практическое задание 8. Векторы


Задание: вывести данные по кредитам в виде 3 векторов (фамилия,
имя, год рождения, сумма кредита, срок погашения, остаток по задолженно­
сти). Использовать функции из библиотеки <vector>.
Таблица 56
Варианты для практического задания 8

Входные данные
вар.
i Проверка на уникальность введенных значений (поле фио)
2 Сортировка элементов по убыванию (по сумме кредита)
3 Сортировка элементов по возрастанию (по задолженности)
Поменять местами четные по значению элементы 2 векторов
4
(срок погашения)
5 Сравнить элементы 3-х векторов (остаток по задолженности)
6 Поменять местами положительные элементы 2-х векторов (год рождения)
7 Сравнить элементы 3-х векторов (сумма кредита)
8 Сортировка элементов по возрастанию (срок погашения)
9 Вывести данные по кредитам, заканчивающимся в текущем году

82
15.3. Потоки ввода (istream)

Окончание табл. 56

Входные данные
вар.
10 Увеличить остаток по задолженности на сумму кредита больше введенной
(в диалоге)
11 Увеличить срок погашения на год для кредитов на сумму меньше введен­
ной (в диалоге)
12 Сортировка элементов по убыванию (год рождения)
13 Уменьшить остаток по задолженности для введенного года рождения (в
диалоге)
14 Вывести процент остатка по кредиту от первоначальной суммы
15 Вывести значения наибольшего остатка по задолженности
16. ДАТА И ВРЕМЯ В ПРОГРАММАХ НА C++

Необходимость в программной обработке времени возникает при раз­


работке систем, обрабатывающих данные реального мира. Сложность по­
добных программ изменяется в широких пределах - от простого отсчета вре­
менного диапазона до реализации логики временных событий.
Функций для работы со временем в языке C++ несколько. Одной из
них является функция clock(), которая подключается к проекту с помощью
заголовочного файла <ctime>. Она позволяет вывести время работы про­
граммы к определенному моменту. С помощью этого можно вычислять,
сколько времени затрачено на тот или иной участок кода.
Таблица 57
Чтение данных из строкового потока
s = “ 12.04.2020 День космонавтики
int dd,mm,yy;
char cc;
char Str[ 100];
stringstream IntStr (s);
InStr » dd » cc » mm » cc » yy;
_______IntStr.getline( Str,100);______________________________________
Время в любой цифровой системе отсчитывается с использованием
счетчиков. Всякая программа, использующая время, должна получать значе­
ния счетчика в любой требуемый момент времени. В программах на языке С
существует библиотечная функция, с помощью которой с 1 января 1970 г.
получают текущее время в секундах.
time_t time( time_t *timer)
Функция time принимает в качестве аргумента указатель на перемен­
ную типа time_t и в эту переменную записывается время момента вызова
функции.
На рис. 21 показан пример, где в окне отладчика отображено значение
текущего времени в числовом виде.
t im e _ t C u rT im e ;
t i m e (й р а г Т іг а е і) ;

Рис. 21. Чтение текущего времени


84
16. Дата и время в программах на C+ +

Непосредственно использовать значения времени можно для вычис­


ления временных интервалов. Разность любых значений - это длина интер­
вала в секундах. Кроме того, добавление интервалов времени в секундах поз­
воляет установить временную метку «будущего». Например,
CurTime=CurTime +3600*24*7
определяет момент времени, смещенный на неделю вперед относительно
текущего.
Таблица 58
Структурированное представление времени
tm _ se c Seconds after m inute (0-59).
tm _ m in M in u tes after h o u r (0-59).
tm _ h o u r H o u r a fter m idnight (0-23).
tm _ m d a y D ay o f m onth (1-31).
tm _ m o n M onth (0-11; January = 0).
tm _ y e a r Y ear (current y e a r m inus 1900).
t m w d a y D ay o f w eek(0-6; Sunday = 0).
tm _ y d a y D ay o f year (0-365; January 1 = 0).
tm _ is d s t

Стандартная библиотека в C++ использует структуру tm для привыч­


ного в отображении представления времени (рис. 22). Это представление
включает в себя: текущее время с точностью до секунд, день, месяц, год. По­
лучить это представление можно, имея значение типа time_t в секундах.

tm *pCurTime;
£CurTimej=localtime CurT ime) ;
□ sf pCurTime 0x009567a0 {tm_sec=51tm_min=ll tm_hour=20 ...} |
CurT * * tm_sec
‘ 51 + 3600*24*7;
pCur' * tm_min 11 іе (& C u rT im e ) ;
tmjiour 20
tmjnday 3
tmjnon 3 = 22;
tm_year 112
* tmjwday 2
C u rT V tm_yday 93 p C u rT im e );
у tmjsdst 0 ie C u r T im e ) ;

Р и с . 22. П олуч ен ие врем ени в виде структуры tm

Функция localtime предназначена для получения времени в виде


структуры tm. На рис. 22 показано окно отладчика, отображающее структур­

85
16. Дата и время в программах на C++

ную переменную времени. Результат возвращается как указатель на струк­


туру tm. Все элементы структуры tm являются целыми числами, т.е. их
можно использовать в арифметических выражениях.
Выполнить преобразование времени в виде структуры tm число се­
кунд позволяет функция mktime. В качестве параметра принимается указа­
тель на структурную переменную, а возвращается число типа time_t. На
рис. 23 показан программный код, позволяющий получить число типа time_t
для нужного дня месяца (в примере 22 числа текущего месяца).
Функция asctimc преобразует время в секундах в символьную неру­
сифицированную строку (рис. 23).
p C u r T im e - > tm _ m d a y = 2 2 ;

C u rT im e — nOctime (p C u r T im e ) ;
^ u r T i m e j = l o c a lt i m e (&C u rT im e ) ;
В 0 pCurTime 0x009 567a0 {tm_sec=51 tr
c h a r *pi &tm_sec 51
p s trc u r: *
11 e ( p C u r T im e ) ;
sf tm_hour 20
$ tmjnday 22
r e t u r n ( ‘S' tmjnon 3
tm_year 112
__________ tmjwday 0
V tm_yday 112
--------- ------- * tm isdst 0

Рис. 23. Преобразование времени из структуры tm в time t

Практическое задание 9. Время получения результата


Задание', определить время работы программы
Таблица 59
Варианты для практического задания 9
№ Представление
Входные данные
вар. выходных данных
i Сравнить время работы функций, заполня­ Наименьший результат из
ющей массив случайными числами и счи­ полученных
тывающей числа с клавиатуры
2 Сравнить время выполнения 2-х способов Наибольший результат из по­
сортировки массива (на выбор: сортировка лученных
пузырьком, вставками, деревом)
3 Получите время, которое пользователь Наименьший результат из
тратит на нажатие клавиши при заполне­ полученных
нии массива из 20-ти целых чисел

86
16. Д ат а и время в программах на ( '

(Окончание табл. 59
№ Представление
Входные данные
вар. выходных данных
4 Сравнить время выполнения 2-х способов сор­ Время работы фрагмента
тировки массива (на выбор: сортировка выбо­ программы
ром, обменами, «гномья»)
5 Получите время, которое пользователь тратит Время работы программы
на нажатие клавиши при заполнении массива без использования си­
из 10-ти вещественных чисел стемных часов
6 Выполнить сортировку элементов массива (на Время работы программы
выбор: сортировка пузырьком, вставками, де­ в миллисекундах
ревом)
7 Сравнить время выполнения 2-х способов сор­ Время программы в се­
тировки массива (на выбор: сортировка слия­ кундах. с дробной частью
нием, быстрая, выбором) (до 2 знаков)
8 Выполнить сортировку элементов массива (на Время работы программы
выбор: сортировка пузырьком, вставками, де­ в миллисекундах
ревом).
9 Сравнить время выполнения 2-х способов сор­ Время работы фрагмента
тировки массива (на выбор: сортировка слия­ программы
нием. быстрая, выбором)
10 Получите время, которое пользователь тратит Время выполнения функ­
на нажатие клавиши при заполнении массива ции, измеренное в цикле
из 25-ти целых чисел
11 Выполнить сортировку элементов массива (на Время работы программы
выбор: сортировка пузырьком, вставками, де­ без использования си­
ревом) стемных часов
12 Получите время, которое пользователь тратит Время работы программы
на нажатие клавиши при заполнении массива в миллисекундах
из 20-ти целых чисел
13 Сравнить время выполнения 2-х видов пораз­ Наименьшее время ра­
рядной сортировки массива боты программы
14 Сравнить время выполнения 2-х способов сор- Время работы программы
гировки массива (на выбор: сортировка слия­ без использования си­
нием, быстрая, выбором) стемных часов
15 Получите время, которое пользователь тратит Время работы фрагмента
на нажатие клавиши при заполнении массива программы
из 30-ти целых чисел

87
17. ОБРАБОТКА ОШИБОК И ИСКЛЮ ЧЕНИЙ

Исполнение любой программы может сопровождаться появлением


сочетаний данных, которые считаются ошибочными. Не учитывать подоб­
ные ситуации - значит строить ненадежную программу. Обработка ошибок
в программах на многих языках может строиться по двум основным
направлениям:
• пассивное реагирование на ошибочную ситуацию;
• активное реагирование на ошибочную ситуацию.
char *pStrCurTime;
pStrCurTiraei = a set ime (pCurTime) ;
................ai pStrCurTime
return 0;

Рис. 24. Преобразование времени из типа time t в строку

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


Таблица 60
Функция, возвращающая и данные, и код ошибки
int MyFunction ( int InpData
{
bool bError = false;
int OutData;
// обработка входных аднных
И ...
// здесь может быть ошибочная ситуация, т.е. bError = true
if (bError)
return -1;
else
return OutData;
_ _ t _________________________________________________________
Пассивный режим основан на возврате оператором return из функции
признака ошибки (табл. 61).
Таблица 61
Проверка ошибки и обработка данных
int Result;
result = Му Function! 100 );______________________

88
17. Обработка ошибок и исключений

Окончание табл. 61

if( Result != -1)


{
// ошибки не было, данные обрабатываются
}
else
_______cout « “Error detected !”;_____________________________________
В некоторых случаях в качестве признака ошибки используется одно из
значений данных, такой стиль программирования применять не рекоменду­
ется из-за высокой вероятности “спутать” полезное и ошибочное значение.
Чтобы разделить ошибочные и полезные значения, выходные пере­
менные переносят в список параметров функций (табл.62).
Таблица 62
Разделение кода ошибки и полезных значений
bool MyFunctionA ( int InpData, int& OutData)
{
bool bError = false;
// обработка входных аднных
// ...
// здесь может быть ошибочная ситуация, т.е. bError = true
return bError;
}______________________________________________________
В качестве возвращаемого оставляют булево значение. Именно оно
позволяет однозначно определить была ошибка или не было. В табл.61 по­
казан программный код, обрабатывающий признак ошибки.
В обоих рассмотренных выше случаях остается открытым вопрос о
том, будет ли проверено возвращаемое значение программным кодом, вы­
звавшим функцию. Если это не сделано, ошибочные данные будут распро­
страняться через последующий процесс обработки.
Таблица 63
Обработка ошибки и данных раздельно
bool fError;
int DataFromFunction;
fError = MyFunctionA( 100, DataFromFunction );
_______if( !fError )__________________________________________________

89
17. Обработка ошибок и исключений

Окончание табл. 63
{
// ошибки не было, данные обрабатываются
}
else
_______co u t« “Error detected !”;___________________________________
В основе активного режима обработки ошибок лежит использование
исключений. Исключение в программе - это специфическая ситуация, кото­
рая возникает после использования ключевого слова throw. Оператор
throw х «выбрасывает» исключение х, которое является переменной или зна­
чением определенного типа. В табл. 64 показан пример функции, которая при
возникновении ошибки выбрасывает «неопределенное» исключение.
Таблица 64
Выброс исключения при возникновении ошибки
void MyFunctionB ( int InpData, int& OutData)
{
bool bError = false;
// обработка входных данных
/ / ...
bError = true;
// здесь можеть быть ошибочная ситуация, т.е. bError = true
if (bError)
throw ;
_______ 1_________________________________________________________
Смысл этого действия в том, что дальнейшее исполнение программ­
ного кода функции прекращается, управление передается в вызвавшую
функцию. Далее возможна одна из двух ситуаций:
• вызвавшая функция обрабатывает исключение и продолжает свое
выполнение;
• вызвавшая функция не обрабатывает исключения. Тогда объект ис­
ключения «пробрасывается» в вызвавшую функцию верхнего уровня и так
далее до тех пор, пока исключение либо не будет обработано одной из функ­
ций программы, либо будет выброшено операционной системе. В этом слу­
чае операционная система аварийно завершает программу, выводя соответ­
ствующее уведомление.

90
1 7. Обработка ошибок и исключений

Таблица 65
Код с функцией, способной генерировать исключения
bool fError;
int DataFromFunction;
fError = MyFunctionA ( 100, DataFromFunction );
if( !fError)
{
// ошибки не было, данные обрабатываются
}
else
cout « “Error detected !”;
_______MyFunctionB( 100, DataFromFunction ); // exception_______________
В табл. 65 приведен программный код, содержащий вызов функции,
способной выбросить исключение. Если это происходит, выполнение про­
граммы завершается выводом сообщения, показанного на рис. 25. Исключе­
ния в коде игнорируются.

Рис. 25. Окно сообщения об исключении

Обработка исключений строится на использовании пары операторов


try и catch. Обработка исключений при использовании try и catch осуществ­
ляется по следующему сценарию:
• последовательно выполняются строки кода в блоке try. Если исклю­
чений не возникло, после блока try исполняется код, размещенный за по­
следним оператором catch;
• если возникло исключение в блоке try, дальнейшее исполнение
кода функции прерывается, и система исполнения программ стремится
найти ловушку catch, соответствующую типу выброшенного исключения.
91
17. Обработка ошибок и исключений

Если ни одна ловушка не сработала, исключение “пробрасывается” в вы­


звавшую функцию;
• выполняется программный код первой подходящей по типу исклю­
чения ловушки. Все ловушки просматриваются сверху вниз. После выпол­
нения кода ловушки делается переход на программный код за последним
оператором ловушки. Исключение считается обработанным, программа про­
должается в обычном режиме.
Таблица 66
Генерация исключений разных типов
void MyFunctionC ( int InpData, int& OutData )
{
bool bError = false;
char sim = 0;
// обработка входных данных
//...
bError = true;
// здесь может быть ошибочная ситуация, т.е. bError = true;
if( bError)
throw 10;
if (sim !=’a’)
throw sim;
}_________________________________________________________
В блок try обычно помещают программный код минимального раз­
мера, поскольку обработка исключений приводит кувеличению общего объ­
ема программы. Это связано с тем, что компилятор дополняет ненадежный
код специальным кодом для восстановления после прерывания.
Таблица 67
Ловушки для разнотипных исключений
йу
{
MyFunctionC( 100, DataFromFunction ); //exception
}
catch(int)
{
// обработка целочисленного исключения, например DataFrom-
_______Function = 1000;_____________________________________________

92
17. Обработка ошибок и исключений

Окончание табл. 67
}
catch(char)
{
// обработка исключения символьного типа, например DataFrom-
Function = ‘а’ + ‘А ’;
_______1_________________________________________________________
В табл. 67 и 67 показан код, генерирующий исключения, и код, обра­
батывающий исключения. В примере генерируются исключения двух ти­
пов - int или char. Для каждого из них в вызывающей функции предусмот­
рена ловушка. Заметим, что catch(...) - это вариант ловушки, которая ловит
любые типы исключений.
Таблица 68
Обработка исключений стандартной библиотеки
try
{
string str( “Micro” );
string rstr( “soft” );
str.append( rstr, 5, 3 ); // позиции 5 в строке rstr не существует
}
catch (out_of_range& e)
{
co u t« “exception: ” « e.what()« endl;
}
catch (exception& e)
{cout « “exception: “ « e.what() « endl;
}
catch (...)
{
a = -1;
}___________________________________________________
Стандартная библиотека C++ выбрасывает ряд исключений опреде­
ленных классов, описанных в самой библиотеке. Их обработка должна быть
сделана при вызове соответствующих функций. В табл. 68 показано, как об­
рабатывается исключение, генерируемое методом append класса string.

93
18. ДИНАМИЧЕСКОЕ ВЫДЕЛЕНИЕ ПАМЯТИ

Задача управления памятью на программном уровне относится к ис­


пользованию оперативной памяти. Создание переменных программы обяза­
тельно связано с потреблением оперативной памяти, объем которой иногда
может сильно ограничиваться характеристиками оборудования.
Для устройств и систем с ограниченным объемом оперативной па­
мяти важно организовать динамическую процедуру выделения и освобож­
дения памяти. Для статических переменных подобное управление невоз­
можно. Как альтернативу, многие языки предлагают возможности динами­
чески выделять и освобождать память.
Любая программа при загрузке для выполнения имеет определённое
распределение областей памяти (табл. 69). Границы каждой области фик­
сированы, любое перемещение границы является ошибкой, исключающей
продолжение выполнения программы. Для хранения команд процессора
выделяется область программного кода. Данная область расположена ря­
дом со стеком.
Таблица 69
Распределение памяти программы
1 Куча
2 Память статистических переменных
3 Программный код
4 Стек

Область стека обычно используется для сохранения адресов и пара­


метров вызываемых функций, а также для хранения промежуточных пере­
менных внутри программных блоков. Использование стека напрямую про­
граммисту не разрешается. Режим заполнения стека данными зависит от ло­
гики работы компилятора.
Стек заполняется «снизу вверх» и при большом количестве вложен­
ных вызовов может перейти границу программного кода. В этом случае фик­
сируется аварийное завершение программы из-за переполнения стека.
В памяти статических переменных помещаются чаще всего глобаль­
ные переменные фиксированного размера, а также переменные, объявлен­
ные с ключевым словом static. Границы рассматриваемой области в про­
цессе выполнения программы не изменяются.

94
18. Динамическое выделение памяти

Куча - область, в которой создаются динамические переменные, со­


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

void* malloc(size_t size)


выделяет непрерывный участок памяти длинной size байт. Если такого
участка выделить не удается, функция возвращает NULL. Получить отказ
функция может, в частности, из-за фрагментированности памяти. Фрагмен-
тированность - это наличие чередующихся занятых и свободных участков в
памяти. Несмотря на наличие суммарного достаточного объема свободной
памяти, запрос может операционной системой не удовлетворяться. Пдчерк-
нем, что требуемый фрагмент должен быть непрерывным.
Другой вариант функции

void* calloc(size_t n, size_t size)


позволяет изменить размер выделенного блока памяти из п элементов задан­
ного размера до size элементов.
Выделенную память можно привести к требуемому типу. Это не вли­
яет на ее размер, но указывает компилятору, как генерировать код для обра­
ботки содержимого этой памяти. Например,

char *S1;
SI = (char*) malloc (100) ;
Функция
void* realloc ( void* ptr, size_t size);
позволяет изменить размер уже выделенной памяти по указателю ptr. Новый
размер памяти должен составлять size байт. Если память вызвать не удалось,
то она возвратит NULL. Новое значение может быть как больше существу­
ющего, так и меньше.

95
18. Динамическое выделение памяти

После работы с выделенной памятью ее всегда следует освобождать


вызовом функции

void free (void* ptr).


Параметр этой функции - указатель. Дальнейшее использование ука­
зателя на освобожденную память является опасным.
В табл. 70 показан программный код, использующий динамическое
выделение памяти для целочисленного массива.
Таблица 70
Использование динамически созданного массива
int main(void)
{
int* ptr = (int*) calloc(10,sizeof (in t)) ;
in ts = 0;
for(int i = 0; i<10 ; i++ )
scanf("%d", &ptr[ i ]);
for(int 1 = 0; i<10 ; i++ )
s+ = ptr[ i ];
printf(“ Summa=%d\n", s );
free( p tr );
return 0;

В C++ для выделения и освобождения памяти введены операторы new


и delete (табл.71).
Таблица 71
Операторы динамического выделения памяти C++
char *р;
р = new char[1024];
//......
delete р;

Оператор new возвращает указатель на экземпляр объекта, создан­


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

96
18. Динамическое выделение памяти

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


не считается ошибкой. Действительно, принятие решений о выделении и
освобождении памяти является прерогативой программиста. В некоторых
языках исполняющая система имеет механизм «сборки мусора», который
собирает «ненужные» не освобожденные участки памяти в единое целое.
Исполняющая система программ на Си и C++ такой функции не поддер­
живает. Если в программе ошибочно не освобождаются области памяти,
возникают “утечки” памяти, т.е. области не доступные для дальнейшей ра­
боты. Значительные утечки памяти могут приводить к аварийному завер­
шению программ.
19. ТЕСТИРОВАНИЕ ПРОГРАММНОГО КОДА

Тестирование -э т о процесс экспериментального оценивания качества


программного кода.
1Іри тестировании решают следующие задачи:
1. стремятся обнаружить ошибки;
2. устанавливают соответствие функции программы и ее специфика­
цию;
3. оценивают надежность программы;
4. оценивают специфические показатели, такие как: уровень защиты,
нагрузочная способность, качество диалогового интерфейса и т.д.
Тестирование не может показать отсутствие ошибок.
Тест - это информационная структура, которая описывает условия
для выполнения некоторого действия, входные данные, результат выполне­
ния с указанием выходных данных и состояния программы (рис.26). Отдель­
ные тестовые случаи составляют совокупность, которая считается полным
тестом программного кода.
Тестовые случаи формулируются на основе содержательного анализа,
исходной спецификации программы и опыта разработки программ.

Структура теста
С о сто я н и е п р о гр а м м ы
Услови я зап уска
п о сле завер ш ени я
п р о гр а м м ы .
раб оты .
Входны е д ан ны е
Вы ходны е д анны е

И д ен ти ф и катор Р езул ьтат О ткло нени я


теста

Рис. 26. Информационные структуры для проведения тестирования

Результаты тестирования заносятся в протокол тестирования (рис. 26).


В табл.72 показан пример программы автоматизированного тест иро­
вания функции. Функция должна открывать заданный файл и добавлять к
его содержимому строку символов. Программный код функции приведен ис­
ключительно для иллюстрации. В реальности код тестерам не известен.

98
19. Тестирование программного кода

Таблица 72
Пример тестирования функции
// тестируемая функция
bool AddInfToFile(char* sPath, char* sText)
{
fstream TextFile;
TextFile.open(sPath,ios_base::app);
TextFile « sText;
TextFile.close();
return true;
}
int _tmain(mt argc, _TCF1AR* argv[])
{
bool Result;
// тест 1
Result = AddInfToFile(“d:\\temp\\info\\filel.txt”,”90901234567
10.05.2020 55”);

// тест 2
Result = AddInfToFile(“d:\\temp\\info\\l)j)a&i
статистики, txt”,”90901234567 10.05.2020 55”);

// тест 3
Result = AddInfToFile(“ ”,”90901234567 10.05.2020 55”);

// тест 4
Result = AddInfToFile(“d:\\temp\\info\\filel.txt”,” ”);

Тест 1 должен завершиться добавлением указанной строки в указан­


ный файл. После запуска теста в заданном каталоге в файле должна по­
явиться добавленная строка. Проверить то, что тест завершается именно так,
следует с помощью Проводника и Блокнота Windows. Можно заметить, что
возвращаемое функцией значение не говорит о том, как завершилась опера­
ция. Это можно отнести к недостаткам разработки, однако на этапе тестиро­
вания подобные вопросы стараются не ставить. Слишком высока цена воз­
врата на ранние этапы проектирования.
Тест 2 ставит своей целью проверку того, что корректно будет создан
файл с кириллическим именем. Контроль результата выполняется с помо­
щью Проводника Windows.
99
19. Тестирование программного кода

Тест 3 предназначен для проверки реакции функции на отсутствие


имени файла: первый параметр вызова является пустой строкой. В зависи­
мости от используемой библиотеки может быть сгенерировано исключение
или возвращен код ошибки. Реакция на тест должна быть зафиксирована в
протоколе.
Тест 4 заключается в записи пустой строки в конец файла. С помощью
Проводника Windows сравнивают длину исходного файла и файла после за­
пуска теста. Они не должны отличаться.
Любую программу потенциально можно протестировать полностью.
Общее число тестов в этом случае совпадает с числом вариантов сочетаний
входных, выходных данных и состояний программы (рис. 27). Даже для не­
сложных программ это число имеет астрономический порядок, поэтому на
практике полное тестирование любой реальной программы невозможно.

Рис. 27. Число тестов для полного тестирования программы

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


емых объектов на классы эквивалентности (рис. 28). Под объектом тестиро­
вания понимаются различные сущности. Например, тестироваться может ис­
ходный программный код путем его анализа экспертами. Или тестируются
требования исходной спецификации: программный продукт должен удовле­
творять всем установленным в ней требованиям. В обоих случаях общей
проблемой является размерность пространства тестирования. Большое
число строк кода или спецификации создают опасность возникновения
ошибки самой проверки. При этом либо правильные объекты будут при­
знаны неправильными, либо неправильные - правильными.
В класс объединяются эквивалентные, по соображениям тестирую­
щего, варианты данных, строки программного кода, разделы спецификации.
Дальнейшее тестирование проводится на отдельных экземплярах объ­
ектов каждого класса. В зависимости от содержания выбирают небольшое
число представителей и, получив положительный исход тестирования, счи­

100
19. Тестирование программного кода

тают протестированным весь класс объектов. Например, тестируя программ­


ный код, выбирают 2-3 функции; при тестировании спецификаций прове­
ряют 5-7 основных разделов.

Рис. 28. Тестовое покрытие области тестирования


ЛАБОРАТОРНЫЕ РАБОТЫ

Лабораторная работа № 1
Изучение консольных приложений и функций
ввода-вывода с консоли

Задание: разработать программу, позволяющую вводить данные с


клавиатуры и выводить их на экран с простейшим форматированием. Инди­
видуальные задания в табл. 1.
Таблица 73
Варианты для лабораторной работы № 1

Входные данные Представление выходных данных
вар.
i 20 двух- и трёхзначных Два столбца: в одном двузначные, во втором
чисел трёхзначные
2 20 символов Два столбца: в одном строчные, во втором про­
писные
3 15 слов Два столбца: в первом слово, во втором - число
букв
4 20 чётных и нечётных чи­ Два столбца: в одном чётные, во втором нечёт­
сел ные
5 10 фамилий и номеров Три столбца: порядковый номер, наименова­
учебных групп ние группы, фамилия
6 20 целых и дробных чи­ Два столбца: в одном целые, во втором дроб­
сел ные
7 20 цифр и букв Два столбца: в первом буквы, во втором цифры
8 10 комплексных чисел Три столбца: модуль, мнимая и действительная
части
9 12 дат в виде дд. мм. гг Четыре столбца по три даты в каждом
10 6 полных фамилий, имён Три столбца: имя, отчество, фамилия
и отчеств
11 10 телефонных номеров Три столбца: порядковый номер, номер сети
мобильных телефонов в (первые три цифры), номер телефона внутри сети
виде ХХХХХХХХХХ
12 5 пар наименований города Три столбца: порядковый номер, код межгорода,
и междугородный код наименование города

102
Лабораторная работа № 1

Окончание табл. 73

Входные данные Представление выходных данных
вар.
13 5 пар наименований Интер­ Три столбца: порядковый номер, адрес
нет-порталов и их адресов портала в Интернет, наименование
14 6 наименований учебных Три столбца: порядковый номер, наименова­
курсов и оценки по ним в чис­ ние учебного курса, наименование оценки
ловом виде (отлично, хорошо, удовлетворительно)

Методические указания
Для решения поставленной задачи следует использовать консольные
функции ввода-вывода библиотеки С и C++.
int printf(char *управляющая строка, список переменных);
int scanf(char *управляющая строка, список переменных);
Оператору « передаются различные значения - строки, значения пе­
ременных, которые выводятся на консоль.
Строки могут содержать управляющие последовательности, которые
интерпретируются определенным образом. Например, последовательность
"\п" интерпретируется как перевод на новую строку. Из других управляю­
щих последовательностей также нередко употребляется "\t", которая интер­
претируется как табуляция.
Для считывания с консоли данных применяется оператор ввода » ,
который принимает два операнда. Левый операнд представляет объект типа
istream (в данном случае объект сіп), с которого производится считывание, а
правый операнд - объект, в который считываются данные.
Оператор ввода » возвращает левый операнд - объект сіп, поэтому
мы можем по цепочке считывать данные в различные переменные.
Таблица 74
Спецификаторы формата в управляющей строке_________
Обозначение Тип

%с Символ
%d Целое десятичное число
%і Целое десятичное число
%е Десятичное число в виде х.хх е+хх

103
Лабораторные работы

Окончание табл. 74

Обозначение Тип

%E Десятичное число в виде х.хх Е+хх

%f Десятичное число с плавающей запятой хх.хххх

%F Десятичное число с плавающей запятой хх.хххх

%g %f или %е, что короче

%G %F или %Е, что короче

%o Восьмеричное число

%s Строка символов

%u Беззнаковое десятичное число

%x Шестнадцатеричное число

%X Шестнадцатеричное число

%% Символ %

%p Указатель

%n Указатель

К командам формата могут быть применены модификаторы 1и h.

Таблица 75
Модификаторы
Обозначение Действие модификатора

%ld Печать long int


%hu Печать short unsigned

%Lf Печать long double

Пример использования функций:


#include <stdio.h>
void main(void)
{
int x;
ргіпИТ”Ввсди іс переменную x:");
scanf("%d",&x);
ргіпНТ"Персмсппая x=%d",x);
}

104
Лабораторная работа № 2

Лабораторная работа № 2
Разработка консольных приложений для числовой
обработки информации

Задание: разработать программу вычисления выходного значения


§утщш.у=/(хі,Х 2,хз,Х4). Тип входных и выходных данных, вид функции за­
даны в табл. 2. Выходное значение и входные должны отображаться на
экране в следующем виде:

Х1 =
Х2=
Х3=
Х4=
Y=
Разработать функцию, которая автоматически заполняет массив из 10
наборов входных данных. Массив затем подвергается обработке, т.е. в цикле
вычисляются значения функции и выводятся на экран в виде
Y l= Y2= Y3= Y4= и т.д.
Варианты индивидуальных заданий приведены в табл. 76.
Таблица 76
Варианты для лабораторной работы № 2
№ Тип входных Тип выходных
Функция
вар. данных данных
i Целые Целое
0.5*,5 + 30 0 * 2 + ° - 1*3 + 504
2 Вещественные Вещественное 0.53* і +3.4*2
12*з - 3 0 * 4

3 Целые Целое *1 sin *2 + *з sin *4


4 Вещественные Вещественное tX(x i - 9 0 ° * 2 ;
tg( хз - 1 9 0 ° х 4/)
5 Целые Целое зf x 1 +*2 + yjx3 + х 4

6 Вещественные Вещественное log 5 (X1 + X 2 ) + I°gx3( 4 + X4 )

105
Лабораторные работы

Окончание табл. 76
№ Тип входн ы х Тип в ы ходн ы х
Ф ункция
вар. дан н ы х данны х
7 Ц елы е Ц елое
0 .5 x f + 300x2 + 0 - 1х | + 50x4
8 В ещ ествен н ы е В ещ ествен н ое
^ + 0 .5 3 * 5
12* | -3 0 * J
9 Ц елы е Ц елое Xj sin *2 + *з sin *4
10 В ещ ествен н ы е В ещ ествен н ое
tg (x i - 9 0 ° * 2 )
tg ( *з - 1 9 0 0 * 4 )
11 Ц елы е Ц елое
+X2 + д^Х3 + X4

12 В ещ ествен н ы е В ещ ествен н ое log5( Xj + x2) + logX3 (4 + x 4 )


13 В ещ ествен н ы е Ц елое
^/о.5х1 + З Х 2 "T + 5 x4

14 Ц елы е В ещ ествен н ое
10.3xi + 0 .4 * 2

V 12x3 - 3 0 4

15 В ещ ествен н ы е Ц елое
^ /x | sin *2 + *3 yjsin x 4
16 Ц елы е В ещ ествен н ое
tg (* lx 2 )
tg ( V x 3 - 4 )
17 В ещ ествен н ы е Ц елое
^/500-X] + *2 •7/x3 +X4 +100
18 Ц елы е В ещ ествен н ое sin(log5( x l + x2)) + b g X3 x4

Методические указания
Для построения программ необходимо использовать математическую
библиотеку стандартной библиотеки С, заголовочный файл для которой
именуется как math.h. Функции библиотеки приведены ниже в табл. 77.
При построении алгоритма следует предусмотреть проверку коррект­
ности вводимых данных (в том числе выход за разрядную сетку) и коррект­
ность промежуточных результатов. Также в файле cmath есть набор полезных
числовых констант, например константа М_РІ хранит значение числа ж.

106
Лабораторная работа № 2

Т а б ли ц а 77
Функции математической библиотеки

Имя Описание

abs Возвращает абсолютную величину числа

acos Арккосинус
asin Арксинус

atan Арктангенс
atan2 Арктангенс с двумя параметрами
ceil Округление до ближайшего большего целого числа
COS Косинус
cosh Гиперболический косинус
exp Вычисление экспоненты
fabs Абсолютная величина (числа с плавающей точкой)
floor Округление до ближайшего меньшего целого числа

fmod Вычисление остатка отделения нацело для чисел с плавающей точкой


frexp Разбивает число с плавающей точкой на мантиссу и показатель степени
ldexp Умножение числа с плавающей точкой на целую степень двух
log 1Іатуральный логарифм
loglO Логарифм по основанию 10

Извлекает целую и дробную части (с учетом знака) из числа с плавающей


modlfay?)
точкой

pow ^y) Результаі возведения х в степень у, ху


sin Синус
si nh 1 иперболический синус
sqrt Квадратный корень
tan Тангенс
tanh 1 иперболический тангенс

107
Лабораторные работы

Лабораторная работа № 3
Разработка консольных приложений,
осуществляющих битовую обработку данных

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


тельность входных бит в выходную. Преобразование включает в себя ло­
гические операции над отдельными битами. Подобным образом чаще всего
обрабатываются пакеты данных, получаемые из сетей различного назначе­
ния. В данной работе рассматривается 32-разрядный пакет, содержащий
следующие поля:
F0 - поле флага, обозначающего принадлежность пакета определён­
ной системе;
F1 - поле типа пакета (команда или данные);
F2 - поле содержания (непосредственная информация о данных или
команде);
F3 - контрольное поле.
Обработка пакета в данной работе заключается в выделении содержи­
мого отдельных полей принятого пакета и контроля ошибок. Пакет вводится
по запросу с клавиатуры в виде 16-ричной символьной комбинации.
Контрольная комбинация вычисляется как побайтная сумма по мо­
дулю 31 содержимого разрядов пакета. Результат обработки выводится на
экран как двоичное содержимое каждого из полей пакета.
В табл. 78 приведены варианты индивидуальных заданий.
Таблица 78
Варианты для лабораторной работы № 3

Разрядность F 1 Разрядность F2 Разрядность F3 Разрядность F4
вар.
i 4 1 22 5
2 6 2 20 5
3 3 2 22 5
4 2 1 24 5
5 3 1 23 5
6 6 1 20 5
7 4 2 21 5
8 3 2 22 5
9 4 2 21 5
10 2 1 24 5

108
Лабораторная работа № 4

Окончание табл. 78

Разрядность F 1 Разрядность F2 Разрядность F3 Разрядность F4
вар.
п 6 2 19 5
12 4 1 22 5

Методические указания
Для выделения отдельных групп разрядов в данной работе предлага­
ется использовать двоичное маскирование разрядов. Маска - это двоичная
комбинация, содержащая двоичные единицы в требуемых разрядах числа.
Например, чтобы выделить старшие 5 разрядов 32-битного слова, исполь­
зуют двоичную маску
11111000000000000000000000000000,
что в 16-ричной системе счисления задается константой F8000000. Выпол­
нив поразрядное логическое умножение любого значения на данную маску
и сдвинув результат на 27 разрядов вправо, получаем число, находящееся в
поле из старших пяти разрядов.
Пример программного кода:
unsigned int Kadr,Mask,Field;
Kadr = 0x88000000;
Mask = OxF8000000;
Field = Kadr&M ask;
Field = Field » 27;
Переменная Field получает двоичное значение
00000000000000000000000010001 ,
означающее, что в старших пяти разрядах переменной Kadr содержалась
двоичная комбинация 10001.

Лабораторная работа № 4
Разработка приложений,
содержащих представление информации таблицами

Задание: разработать программу, позволяющую представлять инфор­


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

109
Лабораторные работы

Число записей не ограничено. Варианты индивидуальных заданий показаны


в табл. 79.
Таблица 79
Варианты для лабораторной работы № 4

Поле 1 Поле 2 Поле 3
вар.
i Наименование пред­ ИНН Ф.И.О. директора
приятия
2 Ф.И.О. работника Дата приема на Номер приказа о приеме на
работу работу
3 Наименование арен­ Срок аренды Наименование арендатора
дуемого помещения
4 Объект недвижимо­ Стоимость Владелец
сти
5 Наименование товара Номер накладной Количество
6 Наименование услуги Договорная цена Отметка о выполнении
7 Наименование пред­ ИНН Ф.И.О. директора
приятия
8 Ф.И.О. работника Ставка месячной Премия
оплаты
9 Наименование арен­ Срок аренды Стоимость аренды в месяц
дуемого помещения
10 Объект недвижимо­ Владелец Адрес
сти
11 Наименование товара Тип товара Место хранения
12 Наименование услуги Содержание Время исполнения

Методические указания
Таблицы на программном уровне рекомендуется описывать перемен­
ными структурного типа. Чтение и сохранение в файл выполняется незави­
симо для каждого поля структуры.
Вывод в C++ может быть буферизован по соображениям производи­
тельности. Это означает, что всё, что выводится в файловый поток, не может
сразу же быть записанным на диск (в конкретный файл). Когда данные бу­
фера записываются на диск, то это называется очисткой буфера. Одним из
способов очистки буфера является закрытие файла.

ПО
Лабораторная работа № 5

Когда в буфере хранятся данные и программа преждевременно завер­


шает своё выполнение (либо в результате сбоя, либо путём вызова метода
exit()), деструкторы классов файлового ввода/вывода не выполняются,
файлы никогда не закрываются, буферы не очищаются и данные теряются
навсегда. Вот почему хорошей идеей является явное закрытие всех откры­
тых файлов перед вызовом exitO.
Также буфер можно очистить вручную, используя метод
ostream: :flush() или отправив std: :flush в выходной поток.
Конструкторы файлового потока принимают необязательный второй
параметр, который позволяет указать программисту способ открытия файла.
В качестве этого параметра можно передавать следующие флаги (которые
находятся в классе ios):
арр - открывает файл в режиме добавления;
ate - переходит в конец файла перед чтением/записью;
binary - открывает файл в бинарном режиме (вместо текстового ре­
жима);
in - открывает файл в режиме чтения (по умолчанию для ifstream);
out - открывает файл в режиме записи (по умолчанию для ofstream);
tranc - удаляет файл, если он уже существует.

Лабораторная работа № 5
Разработка консольных приложений для обработки строк

Задание: разработать программу, запрашивающую у пользователя


текстовые данные, выполняющую требуемую обработку и выводящую ре­
зультат на экран. В табл. 80 приведены варианты индивидуальных заданий.
Таблица 80
Варианты для лабораторной работы № 5

Запрос Содержание обработки
вар.
i Произвольное предложение Подсчитать число предлогов
2 Произвольное предложение Подсчитать число знаков препинания
3 Произвольное предложение Подсчитать число гласных
4 Произвольное предложение Подсчитать число согласных
5 Произвольное предложение Подсчитать количество слов, не счи­
тая предлоги

111
Лабораторные работы

Окончание табл. 80

Запрос Содержание обработки
вар.
6 Произвольное предложение Подсчитать число вхождений в пред­
ложение одного их четырех задан­
ных заранее слов
7 Имя файла в виде Ввести по отдельности имя файла,
сервер:том \каталог1 \каталог2 сервера и всех каталогов
\...имя. расширение
8 Имя файла в виде сервер: том\ката- Подсчитать глубину вложенности
лог1\каталог2\...имя. расширение подкаталогов
9 Два имени файла в виде сервер: Определить, находятся ли они в од­
том\ каталогі \каталог2 \...имя. ноименных подкаталогах и сколько
расширение таких подкаталогов
10 Интернет-адрес файла в виде Ввести по отдельности имя файла,
http://www.сервер.ш\каталог 1\ка- сервера и всех каталогов
талог2\...имя. расширение
11 Интернет-адрес файла в виде Подсчитать глубину вложенности
http://www.сервер.ги\каталог 1\ка- подкаталогов
талог2\...имя. расширение
12 Интернет-адреса двух файлов в Определить, находятся ли они в од­
виде http://www.сервер.ru\ката- ноименных подкаталогах и сколько
лог1\каталог2\...имя. расширение таких подкаталогов

Методические указания
Для построения программы понадобятся функции обработки строк,
объявленные в заголовочном файле string.h. Ниже показаны основные необ­
ходимые функции, показанные в табл. 81.
Таблица 81
Функции обработки строк
Имя Примечания

char *strcat(char *dest, const char *src); дописывает строку src в конец dest

дописывает не более n начальных символов


char *strncat(char *dest, const char
строки src (или всю src, если ее длина
*src, size t);
меньше) в конец dest

112
Лабораторная работа № 5

Окончание табл. 81
Имя Примечания

ищет символ в строке, начиная с головы, и


char *strchrfconst char *. inti: возвращает его адрес, или NULL, если не
найден
ищет символ в строке, начиная с хвоста, и
char *strrchr(const char *. inf): возвращает его адрес, или NULL, если не
найден

лексикографическое сравнение строк (воз­


вращает "0". если строки одинаковые, по­
int strcmnlconst char *. const char *):
ложительное, если первая строка больше, и
отрицательное, если меньше)

int strncmntconst char *. const char *. лексикографическое сравнение первых п


size t): байтов строк

char *strcnv(char *toHere. const char


копирует строку из одного места в другое
*fromHere):
char *strncuv( char *toHere. const char копирует до п байт строки из одного места
* from I lore, size t n): в другое

size t strlenf const char *): возвращает длину строки


char *strstrfconst char *havstack. const находи і первое вхождение строки needle в
char *needle); haystack

I Іример использования функции:


#include <string.h>
#include <stdio.h>
int mam()
{
char *str = "строка симоволов";
char buf[32];
memset(buf, 0, sizeof(buf));// заполнение массива 0
рппіГ("строка: \"%s\"\n\n", str);
рппіГ("массин перед копированием: \"%s\"\n". buf):
strcpy(buf, sir):
рппИ'С'массин после копирования: \"%s\"\n", buf):
return 0;
}
113
ИНДИВИДУАЛЬНОЕ ЗАДАНИЕ

Имеется информация о клиентах телефонной компании и предостав­


ляемых им услугах. Каждая услуга имеет собственный тариф, а каждый
клиент может пользоваться произвольным набором услуг в течение огра­
ниченного интервала времени (соответственно срокам договора). Имеются
данные о фактическом использовании услуг. Вся указанная информация
представлена текстовыми файлами, структура которых выглядит следую­
щим образом.
Файл информации о клиентах содержит фамилию, имя, отчество кли­
ента, номер телефона, дату заключения договора, дату окончания договора,
размер задолженности, допустимый кредит. Каждое поле отделяется запятой,
запись - это строка текста. Пример содержимого в файле следующий:
Иванов Иван Иванович, 9773672365,12.10.2012,12.10.2014,0,0
Петров Иван Васильевич, 9734672311,22.01.2008,
01. 11. 2011 ,210,200
Васильев Илья Васильевич, 9714679805,05.09.2010,
01. 12.2012 ,0,2000
Файл информации об услугах состоит также из записей, состоящих
из полей, разделенных запятыми. Каждая запись включает наименование
услуги, ее код, тариф (в рублях), временной интервал измерения (мин,
сутки, месяц. Если временной привязки нет, ставится символ #). Пример
данных в файле:
Связь внутри сети, 1,0.30, мин
СМС, 2 ,0 .1 5 ,#
Связь с другими мобильными сетями, 3,0.50, мин
Роуминг, 4,10, мин
Международный тариф, 5,50, мин
Файл информации об услугах, оказанных клиентам, включает в себя за­
писи, состоящие из полей номера телефона, кода услуги, даты и времени ее
использования в секундах. Знак # используется в случае, если время не опре­
деляется (например, отправляется СМС). Пример содержимого в файле:
9734672311,1,13.02.2008 13:01:55,300
9734672311.2.28.11.2012 01:32:30, #
9757282392.5.23.09.2013 19:14:00,54

114
Общие требования к разработке

Задание состоит в разработке программы, которая считывает настро­


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

Общие требования к разработке

Каждый файл хранится в том же каталоге, что и разработанная про­


грамма.
Формат файлов текстовый, каждый из них может быть создан тексто­
вым редактором.
Содержание файла настройки определяется вариантом в таблице ин­
дивидуальных заданий (см. ниже).
Параметры настройки записываются в текстовый файл с именем
Param.ini. Каждый параметр - в отдельной строке.
Результирующий отчет записывается в файл с именем Report.txt. Если
информация отсутствует, вывести в файл строку «Нет данных».
Вывести сообщение в окно программы о результатах её выполнения
- есть или отсутствуют данные в результирующем файле. Язык сообщения
английский либо русский на транслите.
Формат данных в файле Report.txt: каждая строка списка отделяется
символами перевода строки. Если в строке несколько полей, они разделя­
ются символами « , ».
Пример выполнения индивидуального задания
Таблица 82
Нулевой вариант индивидуального задания
№ Отчёт Параметры
0 Для заданного номера телефона сфор­ Суммарная стоимость, номер
мировать список предоставленных телефона
услуг, суммарная стоимость которых
не меньше заданной, в течение 3-х по­
следних дней (от момента запуска про­
граммы)

115
Индивидуальное задание

Рис. 29. Пример содержимого файла uslugi.txt

Рис. 30. Пример содержимого файла ispol.txt

Рис. 31. Пример содержимого файла param.ini

Создание соответствующих структур для каждого файла:

struct VVOD // файл param.ini


{
int sum; // суммарная стоимость всех услуг
char Nomer[15]; // считывается заданный номер
};

struct SpisokISPLUslug // файл ispol.txt


{
char TELUSE[15]; //номер телефона пользователя
int Kod; //это номер услуги
int Day; // день
int Mes; // месяц
116
Общие требования к разработке

int Yr; //год


int Chas;
int min;
int sec;
int vremispol; // а это время использования услуги

Создание массива из структур:

INFТARIF InfTarif[5];
USERINF Pols[10];
SpisokISPLUslug IspUsl[20];
VVOD zadanie;
Создание файлов в программе, открытие их для чтения из файла в
структуры следующим алгоритмом:

FILE *Klient;
ermo_t raz = fopen_s(&Klient, "C:\\Users\\acer\\Desktop\\H3\\Pro-
jectlWuser details.txt", "r");
FILE *Tarif;
ermo_t dva = fopen_s(&Tarif, "C:\\Users\\acer\\Desktop\\H3\\Pro-
jectlWuslugi.txt", "r");
FILE *IspUslug;
ermo_t tri = fopen_s(&IspUslug, "C:\\Users\\acer\\Desktop\\H3\\Pro-
jectlWispol.txt", V );
FILE *input;
ermo t chetiri = fopen_s(&input, "C:\\Users\\acer\\Desktop\\H3WPro-
jectlWparam.ini", "r");
if (raz II dva || tri || chetiri)
{
printf_s("He все файлы существуют или имеют некорре-
ткный набор данных\п");
return -1;
}
for (int i = 0; (i < 10) && !feof(Klient); І++)
{
fscanf_s(Klient, "%[A,]s", &Pols[i].Name, 40); fscanf_s(Klient,
"%*c");
fscanf_s(Klient, "%[A,]s", &Pols[i].TelUse, 15);
fscanf_s(Klient, "%*c");

117
Индивидуальное задание

fscanf_s(Klient, "%[A,]s", &Pols[i].PODKL, 12);


fscanf_s(Klient, "%*c");
fscanf_s(Klient, "%[A,]s", &Pols[i].OTKL, 12);
fscanf_s(Klient, "%*c");
fscanf_s(Klient, "%[A,]s", &Pols[i].DOLG, 20);
fscanf_s(Klient, "%*c");
fscanf_s(Klient, "%d", &Pols[i].Balans); fscanf_s(Klient,
"%*c");
}
for (int i = 0; (i < 5) && !feof(Tarif); i++)
{
fscanf_s(Tarif, "%[A ]s", &InfTarif[i].Nazvanie, 40);
fscanf_s(Tarif, "%*c");
fscanf_s(Tarif, "%d", &InfTarif[i].Kod); fscanf_s(Tarif,
"%*c");
fscanf_s(Tarif, "%d", &InfTarif[i].Tarif); fscanf_s(Tarif,
"%*c");
fscanf_s(Tarif, "%d", &InfTarif[i].vremuspol); fscanf_s(Tarif,
"%*c");
}
for (int i = 0; (i < 20) && !feof(IspUslug); i++)
{
fscanf_s(IspUslug, "%[A ]s", &IspUsl[i].TELUSE, 15); fscanf_s(Is-
pUslug, "%*c");
fscanf_s(IspUslug, "%d", &IspUsl[i].Kod); fscanf_s(IspUslug, "%*c");
fscanf_s(IspUslug, "%d%*c", &IspUsl[i].Day);
fscanf_s(IspUslug, "%d%*c", &IspUsl[i].Mes);
fscanf_s(IspUslug, "%d", &IspUsl[i].Yr); fscanf_s(IspUslug, "%*c");
fscanf_s(IspUslug, "%d%*c", &IspUsl[i].Chas);
fscanf_s(IspUslug, "%d%*c", &IspUsl[i].min);
fscanf_s(IspUslug, "%d%*c", &IspUsl[i].sec);
fscanf_s(IspUslug, "%d", &IspUsl[i].vremispol);
if (IspUsl[i].vremispol < 0)
{
IspUsl[i].vremispol = -1;
fscanf_s(IspUslug, "%*c");
}
fscanf_s(IspUslug, "%*c");
}
fscanf_s(input, "%d", &zadanie.sum);

118
Общие требования к разработке

fscanf_s(input, "%*с");
fscanf_s(input, "%s", &zadanie.Nomer, 15);
Алгоритм для определения даты и расчёта задолжности:
for (int j = 0; j < 10; j++)
{
if (((IspUsl[j].Mes - 1) < timeinfo->tm_mon) && ((timeinfo->tm_year -
100 + 2000) == IspUsl[j].Yr))
{
h = MessDay[IspUsl[j].Mes - 1] - IspUsl[j].Day + timeinfo->tm_mday;
if (h <= 3)
{ {
if (memcmp(zadanie.Nomer, IspUsl[j].TELUSE, 12) == 0)
{
if (IspUsl[j].Kod == 1)
{
к += InfTarif[0].Tarif*((IspUsl[)].vremispol + 59) /60); a++;
}
if (IspUsl[j].Kod == 2)
{
к += InfTarif[l].Tarif*((IspUsl|j].vremispol + 59) / 60); b++;
}
if (IspUsl[j].Kod == 3)
{
к += InfTarif[2].Tarif*((IspUsl[)].vremispol + 59) / 60); C + + ;

}
if (IspUsl[j].Kod == 4)
{
к += InfTarif[3].Tarif*((IspUsl|j].vremispol + 59) / 60); d++;
}
if (IspUsl[j].Kod == 5)
{
к += InfTarif[4].Tarif; e++;

else if (((IspUsl[j].Mes - 1) == timeinfo->tm_mon) && ((timeinfo-


>tm_year - 100 + 2000) == IspUslfj], Yr))

119
Индивидуальное задание

{
h = timeinfo->tm_mday - IspUsl[j].Day;
if (h <= 3)
{
{
if (memcmp(zadanie.Nomer, IspUsl[j].TELUSE, 12) == 0)
{
if (IspUsl[j].Kod == 1)
{
k += InfTarif[0].Tarif*((IspUsl[j].vremispol + 59) / 60); a++;
}
if (IspUsl[j].Kod == 2)
{
k += InfTarif[1].Tarif*((IspUsl[j].vremispol + 59) / 60); b++;
}
if (IspUsl[j].Kod == 3)
{
k += InfTarif[2].Tarif*((IspUsl[j].vremispol + 59) / 60); c++;
}
if (IspUsl[j].Kod == 4)
{
k += InfTarif[3].Tarif*((IspUsl[j].vremispol + 59) / 60); d++;
}
if (IspUsl[j].Kod == 5)
{
k += InfTarif[4].Tarif; e++;
}
}
}
}
}
}
Вывод полученных результатов в файл output и закрытие всех файлов:
if (k >= zadanie.sum)
{
if (a > 0) fprintf_s(output, "Связь внутри сети^");
if (b > 0) fprintf_s(output, "CMC\n");
if (c > 0) fprintf_s(output, "Связь с другими сетями^");
if (d > 0) fprintf_s(output, "Роуминг^");

120
Представление результата выполнения индивидуального задания

if (е > 0) fprintf_s(output, "Международный тариф\п");


}
fclose(Klient);
fclose(Tarif);
fclose(IspUslug);
fclose(input);
fclose(output);
return 0;
}
Вариант индивидуального задания определяется соответственно по­
рядковому номеру в списке группы.

Представление результата выполнения индивидуального задания

1. Исполняемый файл программы.


2. Три входных файла с 10-ю записями, придуманными самостоя­
тельно в качестве примера.
3. Отчет, включающий:
• формулировку индивидуального задания;
• описание алгоритма в виде блок-схемы;
• листинг (текст) программы;
• тексты файлов данных;
• контрольный пример в виде входных и выходного файла.
Отчёт загружается в контрольную работу в Moodle (1ms).
Таблица 83
Варианты индивидуальных заданий
№ Отчет Параметры
1 Перечислить услуги, предоставленные указан­ ФИО клиента, дата
ному клиенту в заданном диапазоне времени ( начала диапазона, дата
с... по ...) конца диапазона
2 Для заданного номера телефона сформировать Суммарная стоимость,
список тех предоставленных услуг, суммарная номер телефона
стоимость которых не больше заданной, в тече­
ние последней недели (от момента запуска про­
граммы)

121
Индивидуальное задание

Продолжение табл. 83
№ Отчет Параметры
3 Построить список клиентов, использовавших Наименования двух
услуги двух наименований в указанный времен­ услуг, дата начала диа­
ной промежуток ( с ... по ....) пазона, дата конца диа­
пазона
4 Получить перечень услуг, предоставленных в Минимальное значе­
текущем месяце, с суммарным значением в за­ ние и максимальное
данном диапазоне значений значение диапазона
5 Определить список клиентов и список услуг, Номер месяца
которыми они пользовались за указанный месяц
6 Перечислить ФИО клиентов, пользовавшихся Наименование услуги
указанной услугой в дневное время
7 Сформировать список и стоимость услуг, кото­ ФИО клиента
рыми пользовался указанный клиент в текущем
квартале
8 Получить список клиентов, которые имеют за­ Сумма задолженности
долженность не более заданной и не пользова­
лись услугами в течение предыдущего месяца
от момента запуска программы
9 Перечислить даты заключения договоров и теле­ Сумма стоимости
фонные номера клиентов, использовавших услуги услуг
на сумму, не менее заданной, в течение текущей
недели (от момента запуска программы)
10 Сформировать список услуг, не использовав­ Список ФИО пяти кли­
шихся в 1-м квартале текущего года заданными ентов
пятью клиентами
11 Получить перечень услуг и телефонных номе­ Список ФИО клиентов
ров для заданных клиентов, с которыми заклю­
чён договор во 2-м квартале нынешнего года
12 Построить список клиентов, которые имеют за­ Три вида услуг, сумма
данную сумму кредита и задолженности и не кредита и долга
пользуются указанными тремя видами услуг
13 Перечислить даты начала и окончания догово­ Наименования трех
ров, заключенных на текущей неделе (от мо­ услуг
мента запуска программы), использовавших 3
указанные услуги
14 Сформировать список услуг, использовавшихся Список ФИО клиентов
указанными клиентами в ночное время
15 Сформировать список номеров клиентов, ис­ Наименование услуги,
пользовавших указанную услугу хотя бы в од­ первый и второй диа­
ном из двух заданных временных интервалов пазон времени

122
Представление результата выполнения индивидуального задания

Окончание табл. 83
№ Отчет Параметры
16 Определить список клиентов, сумма потреблен­ Диапазон стоимости
ных услуг для которых за последние 3 недели
(от момента запуска программы) была бы в за­
данном диапазоне
17 Определить список услуг, которыми пользова­
лись клиенты со сроком окончания договора до
конца следующего месяца (от момента запуска
программы)
18 Получить общую длительность телефонных Наименование двух
разговоров указанного вида для клиентов, за­ услуг по разговорам
ключивших договоры в текущем месяце
19 Сформировать список клиентов, которые не ис­ Список из 3 услуг, диа­
пользовали указанные 3 услуги в заданном диа­ пазон времени
пазоне времени с... по ...
20 Построить список услуг, которые использова­ ФИО двух клиентов
лись двумя клиентами в прошедшем году (от
момента запуска программы)
21 Подсчитать суммарные платежи для 3 заданных Список 3 услуг
услуг, которые использовались клиентами в
прошедшем квартале (от момента запуска про­
граммы)
ПРИМЕРЫ ТЕСТОВЫХ ВОПРОСОВ

1. Какая программа является ПРАВИЛЬНОЙ?


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

2. Какая программа является НАДЁЖНОЙ?


а) программа, которая соответствует исходному заданию на разработку;
б) программа, которая не содержит ошибок;
в) программа, которая не даёт ошибочных результатов;
г) программа, которая работает без сбоев и отказов в течение задан­
ного времени.

3. Что означает показатель работы программы в "реальном масштабе


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

4. Что такое производительность программы?


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

5. Какой из перечисленных ниже показателей характеризует качество


программы:
а) число обнаруженных ошибок на 1000 строк исходного кода;
б) число не выявленных ошибок на 1000 строк исходного кода;

124
Примеры тестовых вопросов

в) общее число строк исходного кода;


г) общее число выявленных и не выявленных ошибок в исходном коде.

6. Что должно быть сделано на этапе постановки задачи при разра­


ботке программы?
а) выбрана среда разработки программы;
б) определены тесты конечного продукта;
в) разработан макет программы;
г) сформулированы требования к программе.

7. Какая из методологий чаще всего используется на этапе тестиро­


вания?
а) методология "черного" ящика;
б) методология "белого" ящика;
в) методология составления требований к программе;
г) методология отладки программного кода.
8. Какой этап разработки программы направлен на оценку ее каче­
ства?
а) этап моделирования;
б) этап постановки задачи;
в) этап тестирования;
г) этап кодирования и отладки.
9. Какова цель этапа моделирования в процессе разработки про­
граммы?
а) оценить работоспособность программы;
б) оценить возможность реализации задания на разработку про­
граммы;
в) оценить качество разработанной программы;
г) оценить параметры защиты разрабатываемой программы.

10. Каким из перечисленных ниже свойств должен обладать алгоритм


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

125
Примеры тестовых вопросов

в) описываться блок-схемой;
г) давать одни и те же результаты при одних и тех же исходных дан­
ных.
11. Каким из перечисленных ниже свойств должен обладать алгоритм
работы программы?
а) содержать в себе только последовательно выполняемые действия;
б) описываться с помощью псевдокода;
в) получать результат за ограниченное число шагов;
г) позволять моделировать случайность.
12. Кокой элемент блок-схемы обязателен для изображения алго­
ритма?
а) параллельное ветвление;
б) начало;
в) параллельное слияние;
г) условие.
13. Какие элементы блок-схемы позволяют описать цикл обработки
массива?
а) действие + Условие;
б) начало + Конец;
в) параллельное ветвление + Действие;
г) параллельное слияние + Действие + Начало + Конец.

14. Алгоритм требует, чтобы были выполнены Действие А и Действие


В, после чего программа должна завершиться. Что изображено неверно на
блок-схеме?
а) последовательность выполнение Действия А и действия В;
б) начало выполнения алгоритма;
в) завершение выполнения алгоритма;
г) все изображено верно.

15. Какая из функций на листинге объявлена, но не определена?


#include "stdafx.h"
#include
using namespace std;

126
Примеры тестовых вопросов

void MyPrint(char*);
int _tmain(int argc, _TCHAR* argvf])
{
char sl,s2,s3;
co u t« "S e t symbol
c in » si;
return 0;
}
а) iostream;
б) MyPrint;
в) _tmain;
r) cout.

16. Какая из функций на листинге не объявлена, но определена?


#include "stdafx.h"
#include

using namespace std;

void MyPrint(char*);

int _tmain(int argc, TCHAR* argv[])


{
char sl,s2,s3;
co u t« "S et symbol
c in » si;
return 0;
}
а) _tmain;
б) MyPrint;
в) iostream;
r) cout.
17. Какое имя имеет формальный параметр функции, текст которой
показан ниже?
void MyPrint(char* cString)
{
char HelloString[] = "Hello,";
co u t« endl « HelloString ;
127
Примеры тестовых вопросов

cout << cString << " !";


}
а) HelloString;
б) void;
в) MyPrint;
г) cString.

18. Какое значение имеет переменная Y в точке 2 функции main() ?


int Function1( int A)
{
int Y;
Y=100;
A= Y - A;
return A;
}
int Function2( int B)
{
int Y;
Y=B - 10;
B= sqrt( Y);
return B;
}
int main()
{
int X, Y;
X=Function1( 10 ); // точка 1
Y=Function2( 19 );
} // точка 2
а) неопределённое;
б) 9;
в) 0;
г) 3.

19. Какое значение имеет переменная Y в точке 1 функции main() ?


int Function1( int A)
{
int Y;

128
Примеры тестовых вопросов

Y=100;
A= Y - A;
return A;
}
int Function2( int B)
{
int Y;
Y=B - 10;
B= sqrt( Y);
return B;
}
int main()
{
int X, Y;
X=Function1( 10 ); // точка 1
Y=Function2( 19 ); // точка 2
}
а) неопределённое;
б) 100;
в) 90;
г) 0.
20. Какие переменные программы называются глобальными?
а) переменные, действительные во всех строках программного кода
одной функции;
б) переменные, действительные во всех строках программного кода
файла, в котором находятся функции;
в) переменные, действительные для всех строк программного блока;
г) переменные, которые используются после запуска программы.
21. Какие переменные программы называются статическими?
а) переменные, изменяющие своё значение только после выполнения
над ними статических операций;
б) переменные, сохраняющие своё значение даже после выполнения
над ними арифметических операций;
в) переменные, сохраняющие своё значение после завершения функ­
ции;
129
Примеры тестовых вопросов

г) переменные, сохраняющие своё значение на протяжении выполне­


ния кода функции.

22. Что такое тип в языке C++ ?


а) операция, применимая к некоторой разновидности данных;
б) операция, применимая к любой разновидности данных;
в) разновидность данных, к которым применимы только любые опера­
ции;
г) разновидность данных, к которым применимы только определённые
операции.

23. Какой из типов относится к базовым типам C++ ?


а) sizeof;
б) file;
в) short;
г) string.

24. Какой язык программирования называют типизированным?


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

25. Какое из приведённых выражений правильно вычисляет число


элементов в массиве InpNumber[ ] (см. описание массива ниже) ?
int I;
float InpNumbers[ArrayLength];
а) sizeof(InpNumbers) * sizeof(float);
б) sizeof(InpNumbers) / sizeof(float);
в) sizeof(InpNumbers);
r) sizeof(float) / sizeof(InpNumbers).

26. Какое из неравенств является верным?

130
Примеры тестовых вопросов

а) sizeof(char) = sizeof(double);
б) sizeof(char) > sizeof(double);
в) sizeof(char) < sizeof(double);
г) sizeof(char) > sizeof(double) + 1.

27. Что такое тип в языке C++?


а) обозначение для переменной в памяти;
б) обозначения набора операций над содержимым памяти;
в) обозначение области в памяти;
г) обозначение семейства переменных.

28. Для чего предназначен компоновщик объектного кода программ?


а) для объединения в проекте файлов исходного кода *.срр;
б) для компоновки заголовочных файлов *.h;
в) для замены ссылок на исполняемый код вызываемых функций;
г) для запуска программ в операционной системе.

29. Для чего предназначена исполняющая система программ?


а) для повышения правильности исполнения программного кода;
б) для компоновки объектного программного кода;
в) для компиляции исходного программного кода;
г) для увеличения надежности их исполнения.

30. В чем достоинство компиляции программ перед их исполнением?


а) в возможности обнаружить некоторые синтаксические ошибки;
б) в возможности обнаружить все синтаксические ошибки;
в) в возможности автоматически исправить любые ошибки;
г) в возможности избежать синтаксических ошибок при написании
программного кода.

31. В чем недостаток исполнения программы в режиме интерпретации?


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

131
Примеры тестовых вопросов

32. Какой символ будет содержать переменная s2 после выполнения


программного кода, показанного ниже?
char si, s2;
si = ' К
s2 = sl - 1;
s2—;
а) 'K';
б) 'И';
в) '3';
г) 'Ж'.
33. Какой символ будет содержать переменная s2 после выполнения
программного кода, показанного ниже?
char sl,s2;
si =' 5' ;
s2 = si + 1;
s2++;
а) '8';
б) 7';
в) '6';
r) '5'.

34. Какой символ будет содержать переменная s2 после выполнения


программного кода, показанного ниже?
char sl,s2;
si = Т
s2 = si + 1;
s2++;
а) символ 1E
б) символ 1Д
в) символ 1Г
г) символ 1В '.

35. В каком из перечисленных случаев переменная X имеет наиболь­


ший диапазон изменения?
а) long X;
б) double X;
132
Примеры тестовых вопросов

в) float X;
г) long long X.

36. Можно ли за счёт использования функции _finite() избежать пере­


полнения при арифметических вычислениях ?
а) можно, если использовать при этом переменные типа double;
б) нельзя, если использовать при этом переменные типа float;
в) можно, если использовать при этом переменные типа double или
float;
г) нельзя ни при каких условиях.
37. Как ведёт себя программа на C++, если в процессе арифметиче­
ских вычислений возникает переполнение?
а) продолжает свою работу;
б) аварийно завершается, если операция выполнялась над числами
типа int;
в) аварийно завершается, если операция выполнялась над числами
типа double или float;
г) аварийно завершается в любом случае.
38. Какое значение примет переменная Y после выполнения приве­
дённого участка программного кода?
int X , Y ;
X=3;
Y=2 ;
Y= Y&X;
а) 1;
б) 2;
в) 6;
г) 3.
39. Какая из поразрядных операций используется для маскирования
разрядов?
а) логическое отрицание;
б) логическое суммирование по модулю 2;
в) логическое ИЛИ;
г) логическое И.
133
Примеры тестовых вопросов

40. Строка в языке C++ - это ...


а) массив символьного типа с ограничителем ' \ 0 ';
б) массив любого типа с ограничителем ' \ 0
в) массив символьного типа с ограничителем ' \ п ';
г) массив целого типа с ограничителем ' \ 0

41. Сколько символов ' \ 0 ' должно быть в символьной строке?


а) чётное число;
б) нечётное число;
в) ровно один;
г) по крайней мере один.

42. Какая из перечисленных функций выполняет объединение двух


строк в одну?
а) strstr ( . . . ) ;
б) strcpy ( . . . ) ;
в) strcat ( . . . ) ;
г) strcmp ( . . . ) .

43. Какая из перечисленных функций выполняет копирование одной


строки в другую?
а) strstr ( . . . ) ;
б) strcpy ( . . . ) ;
в) strcat ( . . . ) ;
г) strcmp ( . . . ) .

44. Какое значение примет переменная X после выполнения про­


граммного кода, показанного ниже?
intX , Y;
int * Z;
Х= 3;
Y= 2;
Z = & X;
* Z = X + Y;
X++;

134
Примеры тестовых вопросов

а) 3;
б) 2;
в) 6;
г) 5.
45. Какую информацию выведет на экран программный код, показан­
ный ниже?
char sArray[] = "Программа из 20 строк";
printf (" % s " , & sArray [ 13 ] ) ;
а) строк;
б) 20 строк;
в) из 20 строк;
г) программа из 20 строк.

46. Прототип функции SomeFunc показан ниже. Как передаются ей


параметры?
void SomeFunc( int х, char *у);
а) параметр X по ссылке, параметр Y по ссылке;
б) параметр X по значению, параметр Y по значению;
в) параметр X по ссылке, параметр Y по значению;
г) параметр X по значению, параметр Y по ссылке.

47. Какой из параметров функции SomeFunc изменит значение пере­


менной, фактически указанной при вызове этой функции?
void SomeFunc( int х, char *у)
{
*у = 120+ х;
х = *у + 1;
}
а) параметр X и параметр Y;
б) только параметр X;
в) только параметр Y;
г) ни один из параметров.

48. Какой из параметров функции SomeFunc изменит значение пере­


менной, фактически указанной при вызове этой функции?

135
Примеры тестовых вопросов

void SomeFunc( int х, char& у)


{
у = 120 + х;
х = у + 1;
}
а) только параметр X;
б) только параметр Y;
в) параметр X и параметр Y;
г) ни один из параметров.
49. Выберите правильный ответ. После выполнения функции SomeFunc
в вызвавшей её функции ...
void SomeFunc( int х, char& у)
{
у = 120 + х;
х = у + 1;
}
а) изменится значение второго параметра;
б) изменится значение первого параметра;
в) изменятся оба параметра;
г) не изменятся оба параметра.
50. Как передаются массивы для обработки в функциях?
а) по имени массива;
б) по значению первого элемента массива;
в) по адресу первого элемента массива;
г) по имени массива и числу его элементов.
51. Массив обрабатывается некоторой функцией. Как эта функция мо­
жет возвратить результат обработки массива?
а) через значение первого элемента;
б) через значение первого элемента и количество элементов в массиве;
в) через статическую переменную того же типа, что и массив;
г) через указатель на первый элемент массива.
52. В тексте программного кода (см. ниже) необходимо вместо знака?
вставить правильный вариант выражения для передачи массива Х[20] для
обработки в функцию MathFunction и получения результата обработки.

136
Примеры тестовых вопросов

void MathFunction ( int * )


int main()
{
int X [ 20 ] ;
MathFunction (? ) ;

}
а) &X[20];
б) &X[0];
в) &X;
г) X.

53. Функция MathFunction предназначена для того, чтобы обрабаты­


вать числовые массивы типа int. Какой из перечисленных ниже шаблонов
функции соответствует указанной цели?
а) void MathFunction ( int * );
б) int * MathFunction ();
в) void MathFunction ( in t);
r) int MathFunction ().

54. Какие из приведённых свойств являются общедоступными чле­


нами класса, описанного ниже?
а) MaxAge;
б) StudTable;
в) оба указанных;
г) ни один из указанных.

55. Какие из приведённых методов являются общедоступными чле­


нами класса, описанного ниже?
а) AddStudent(...);
б) Students();
в) оба указанных;
г) ни один из указанных.

56. Какие из приведённых свойств являются закрытыми членами


класса, описанного ниже?

137
Примеры тестовых вопросов

а) StudentField;
б) Students;
в) MinAge;
г) Age.

57. Какие из приведённых свойств класса, описанного ниже, не до­


ступны пользователям класса, но доступны наследникам класса?
а) StudentField;
б) StudTable;
в) TableCount;
г) MinAge.

58. Переменная Group является свойством класса Product. Какой из


перечисленных ниже вариантов обращения к свойству Group экземпляра
объекта Obj является синтаксически верным?
а) Obj.Group;
б) Obj::Group;
в) Obj->Group;
г) Product.Group.
59. Переменная Group является свойством класса Product. Какой из
перечисленных ниже вариантов обращения к свойству Group через указатель
Obj на экземпляр объекта является синтаксически верным?
а) Obj::Group;
б) Obj->Group;
в) Obj.Group;
г) Product. Group.

60. Метод Groupe() является методом класса Product. Какой из пере­


численных ниже вариантов обращения к методу Groupe() экземпляра объ­
екта Obj является синтаксически верным?
а) Product.Groupe();
б) Product->Groupe();
в) Obj.Groupe();
г) Obj->Groupe().

138
Примеры тестовых вопросов

61. Метод Groupe() является методом класса Product. Какой из пере­


численных ниже вариантов обращения к методу Groupe() через указатель
Obj на экземпляр объекта является синтаксически верным?
а) Product.Groupe();
б) Product->Groupe();
в) Obj.Groupe();
г) Obj->Groupe().

62. Переменная описана как fstream OutFile. Какая из функций откры­


вает файл для записи, не сохраняя его прежнее содержимое?
а) OutFile.open("NewFile.txt", ios::out);
б) OutFile.open("NewFile.txt", ios::app);
в) OutFile.close("NewFile.txt", ios::in);
г) OutFile.close(L"NewFile.txt", ios::clr);

63. Переменная описана как fstream OutFile. Какая из строк приведен­


ного программного кода записывает в файл символьный массив aStr?
а) OutFile » aStr;
б) OutFile « aStr;
в) OutFile = aStr;
г) OutFile :: aStr;

64. В файл нужно записать массив строк. Какого типа необходимо


описать переменную для вывода в файл?
а) string *;
б) sstream;
в) fstream;
г) char *.

65. Из файла нужно считать массив строк. Какого типа необходимо


описать переменную для ввода из файла?
а) string *;
б) sstream;
в) char *;
г) fstream.

139
Примеры тестовых вопросов

66. Какое из выражений перемещает указатель открытого файла в его


начало:
а) OutFile.seekp(0,ios::beg);
б) OutFile.seekp(-l,ios::end);
в) OutFile.seekp(-l,ios::cur);
г) OutFile.seekp(l,ios::beg);
67. Какое из выражений перемещает указатель открытого файла в его
конец:
а) OutFile.seekp(0,ios::beg);
б) OutFile.seekp(0,ios::end);
в) OutFile.seekp(-l,ios::cur);
г) OutFile.seekp(l,ios::beg);
68. Какое из выражений перемещает указатель открытого файла на
предыдущий символ?
а) OutFile.seekp(l,ios::cur);
б) OutFile.seekp(-l,ios::end);
в) OutFile.seekp(-l,ios::cur);
г) OutFile.seekp(l,ios::beg);
69. Какое из выражений перемещает указатель открытого файла на
следующий символ?
а) OutFile.seekp(-l,ios::cur);
б) OutFile.seekp(-l,ios::end);
в) OutFile.seekp(l,ios::beg);
г) OutFile.seekp(l,ios::cur);
70. Переменная объявлена как stringstream S. Какая из перечисленных
ниже операций допустима над переменной S ?
а) S » х;
б) S = 0;
в) S++;
г) b=(S == 0);

71. Какого типа должна быть переменная Z, чтобы для нее можно
было выполнить операцию Z « х ?

140
_________________________Примеры тестовых вопросов_________________________

а) stringstream;
б) time t;
в) string;
г) struct.

72. Что такое строковый поток?


а) адрес памяти, в которой может сохраняться строка символов;
б) символьный массив с ограничителем;
в) особый вид строк со специальной кодировкой;
г) объект, в который можно вывести информацию оператором « •

73. Как получить строку из строкового потока?


а) используя метод ореп(...);
б) используя метод c_str() класса строк;
в) используя метод str() класса строкового потока;
г) используя оператор » .

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


а) time( time_t t );
б) localtime( time_t t );
в) mktime ( tm t );
г) asctime( time_t t ).

75. Какая функция позволяет получить текущее время в структуриро­


ванном виде ( структуры tm )?
а) time( time_t t );
б) localtime( time t );
в) mktime ( tm t );
r) asctime( time t t ).

76. Какая функция позволяет получить время из структуры tm в виде


числа секунд?
а) time( time t t );
б) localtime( time_t t );
в) asctime( time_t t );
r) mktime ( tm t ).

141
Примеры тестовых вопросов

77. Какой из операторов C++ предназначен для динамического выде­


ления памяти?
а) new;
б) delete;
в) set;
г) namespace.
78. Какой из операторов C++ предназначен для освобождения дина­
мически выделенной памяти?
а) new;
б) delete;
в) set;
г) namespace.
79. Какая функция библиотеки позволяет динамически выделять па­
мять?
а) mswap(...);
б) memcopy(...);
в) malloc(...);
г) free().
80. Какая функция библиотеки позволяет освободить динамически
выделять память?
а) memswap(...);
б) memcopy(...);
в) malloc(...);
г) free().
81. Какое из перечисленных преобразований является безопасным?
а) типа double в тип char;
б) типа double в тип long;
в) типа int в тип short;
г) типа int в тип long.

82. Какое из перечисленных преобразований является опасным?


а) типа int в тип double;
б) типа int в тип string;

142
Примеры тестовых вопросов

в) типа int в тип char;


г) типа int в тип float.
83. Как называется функция преобразования строки в число с плава­
ющей точкой?
а) atoi(...);
б) strtod(...);
в) _itoa(...);
г) _ecvt(...).
84. Как называется функция преобразования целого числа в строку?
а) _itoa(...);
б) atoi(...);
в) _ecvt(...);
г) strtod(...).
85. Что такое контейнер?
а) класс объектов, предназначенный для хранения объектов других
классов;
б) класс объектов, использующийся для хранения программного кода;
в) класс объектов для хранения массивов;
г) класс объектов для хранения таблиц.
86. Что такое итератор?
а) объект для указания одного из контейнеров;
б) объект для указания элементов контейнера;
в) объект для указания алгоритма;
г) объект для указания позиции в файле.
87. Какой объект определяется в приведённом программном коде?
а) вектор таблиц;
б) итератор для таблицы;
в) итератор для вектора;
г) список итераторов.

88. Какого типа элементы может содержать контейнер, описанный в


приведённом программном коде?

143
Примеры тестовых вопросов

а) любые типы;
б) строковые потоки;
в) строки символов;
г) целые числа.

89. Какая из функций может быть использована как предикат сравне­


ния для алгоритма поиска find?
а) bool function(char e l , char e2);
б) struct tm function(char e l , char e2);
в) void function(char e l , char e2);
r) fstream function(char e l , char e2).
90. Для каких типов элементов в контейнере может использоваться
алгоритм поиска find?
а) только для строк;
б) для любых типов;
в) только для чисел;
г) только для структур.

91. Оценка сложности последовательного поиска определяется выра­


жением:
а) о( N );
б) o(logN );
в) o(N **2);
г) о( N log N ).
92. Оценка сложности бинарного поиска определяется выражением:
а) о( N );
б) о( log N );
в) o(N **2);
г) о( N log N ).

93. Какой оператор может быть перегружен при использовании алго­


ритма последовательного поиска?
а) >;
б) ++;

144
Примеры тестовых вопросов

в) ==;
г)
94. Какой оператор должен быть перегружен при использовании ал­
горитма бинарного поиска?
а) !=;
б) >=;
в) <=;
г) ==.
95. Чем отличается контейнер т а р от контейнера vector?
а) наличием ключей у каждого элемента;
б) наличием индекса у каждого элемента;
в) ограничением на тип каждого элемента;
г) ограничением на число элементов в контейнере.
96. Какова сложность поиска в контейнере шар?
а) о( N );
б) о( log N );
в) о( N log N );
г) o(N **2).
97. Требуется ли сортировка элементов контейнера т а р перед поис­
ком?
а) требуется всегда;
б) требуется всегда, если элементы не являются целыми числами;
в) не требуется;
г) не требуется, если элементы являются целыми числами.
98. Какой из операторов должен быть перегружен для поиска в кон­
тейнере тар ?
а) ==;
б) !=;
в) любой из двух перечисленных выше;
г) операторы перегружать не требуется.
99. Выберите выражение, определяющее сложность пузырьковой сор­
тировки:

145
Примеры тестовых вопросов

а) о( N **2);
б) о( N );
в) о( log N );
г) о( N log N ).
100. Выберите выражение, определяющее сложность быстрой сорти­
ровки:
а) o(N **2);
б) o ( Nl o g N) ;
в) о( log N );
г) о( N ).
101. Какой из операторов предназначен для генерации исключения?
а) throw;
б) try;
в) catch;
г) exception.
102. Какой из операторов используется для указания блока программ­
ного кода, при выполнении которого возможны исключения?
а) catch;
б) try;
в) throw;
г) exception.

103. Какой оператор предназначен для обработки сгенерированного


исключения?
1) throw;
2) try;
3) catch;
4) exception.
104. Как используется оператор catch при обработке исключений?
а) оператор catch прерывает выполнение программы при появлении
исключения;
б) оператор catch позволяет описать тип генерируемого исключения;
в) оператор catch указывает на опасный участок программного кода;

146
Примеры тестовых вопросов

г) оператор catch связывает программный код обработки исключения


с его типом.

105. Какой из способов реагирования на ошибку в функции можно


считать более надёжным?
а) генерацию исключения;
б) возврат кода ошибки;
в) вывод текстового сообщения на экран;
г) прекращение выполнения функции.

106. Какой из способов реагирования на ошибку может позволить


продолжить выполнение программы несмотря на ее ошибку?
а) генерацию исключения;
б) возврат кода ошибки;
в) вывод текстового сообщения на экран;
г) прекращение выполнения функции.

107. Куда передаётся управление в программе, если в блоке try сгене­


рировано исключение?
а) оператору, следующему за оператором throw;
б) оператору, следующему за блоком try;
в) первому подходящему по типу исключения оператору catch;
г) первому подходящему по типу исключения оператору throw.

108. Куда передаётся управление в программе, если в блоке try не сге­


нерировано исключение?
а) оператору, следующему за оператором throw;
б) первому подходящему по типу исключения оператору catch;
в) первому подходящему по типу исключения оператору throw;
г) оператору, следующему за последним оператором catch.

109. Как используется стек программы?


а) для хранения переметров вызываемых функций, адресов возврата, а
также локальных переменных функций;
б) для хранения программного кода и глобальных, и статических пере­
менных;

147
Примеры тестовых вопросов

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


г) для хранения динамически созданных переменных.

110. Как используется КУЧА программы?


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

111. Что такое фрагментация памяти?


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

112. Какое ограничение существует при обслуживании запросов на


динамическое выделение памяти?
а) размер участка не должен превышать 32 Кбайт;
б) общий объём фрагментов свободной памяти должен быть не меньше
запрошенной длины;
в) общий объём фрагментов свободной памяти должен быть не меньше
размера стека программы;
г) участок требуемого размера должен быть непрерывным.

113. Можно ли с помощью тестирования доказать отсутствие ошибок?


а) нельзя;
б) можно;
в) можно, если их использовать при разработке программного кода;
г) нельзя, если их не использовали при отладке.

148
Примеры тестовых вопросов

114. Какой приём используют при невозможности полного тестирова­


ния программы?
а) ограничиваются отладкой;
б) применяют случайное тестирование;
в) множество данных разбивают на классы и тестируют программу на
представителях классов;
г) программу разбивают на классы и тестируют классы независимо.
115. Что такое тестовое покрытие?
а) общее число возможных тестов;
б) общее число классов тестов;
в) тесты, соответствующие каждой ситуации в программе;
г) тесты, которые соответствуют классам ситуаций в программе.
116. Ниже приведён программный код. Какое из выражений позволит
явно вызвать функцию са1с() из любой области программы:
а) ~са1с();
б) smp::calc();
в) calc();
г) extern calc();
117. Допускается ли в языке C++ объявление функций с одинаковыми
именами?
а) да, если полностью совпадает тип возвращаемого значения, количе­
ство и типы параметров;
б) нет, если совпадает тип возвращаемого значения;
в) да, если различается хотя бы либо тип возвращаемого значения,
либо тип хотя бы одного параметра, или общее число параметров;
г) нет, ни при каких условиях.
118. До какого момента продолжают тестирование программы?
а) до полного выявления всех ошибок;
б) до уменьшения интенсивности обнаружения ошибок до требуемого
уровня;
в) до момента прогона всех имеющихся тестов;
г) до тех пор, пока в программе делают существенные изменения.

149
ЗАКЛЮ ЧЕНИЕ

Специализация в области информационной безопасности немыслима


без знаний принципов разработки программ. На сегодняшний день суще­
ствует достаточно много технологий программирования и языков програм­
мирования.
Авторам представляется, что со временем это разнообразие сни­
жаться не будет. Поэтому важно изучить и понять основные принципы про­
граммирования прикладных задач, осознать творческий характер процесса
разработки программ.
Настоящее учебное пособие (кроме изложения теоретического мате­
риала) содержит значительную долю материала для практической работы и
самоконтроля. Это не случайно. Невозможно анализировать информацион­
ную безопасность, не разбираясь в тонкостях создания и работы программ.
Нельзя глубоко разбираться в деталях программирования, не пройдя путь
разработки реальных программ. Авторы надеются, что настоящее учебное
пособие даст читателю полезное знание, навыки и умения в области техно­
логии, методов и языков программирования.
СПИСОК ЛИТЕРАТУРЫ

1. Рейтинг языков программирования - URL: http://www.tiobe.com/


index, php/content/company /Home.html
2. Павловская, Т. А. C/C++. Программирование на языке высокого уровня
[Текст]: Учебник для студ. вузов. Т. А. Павловская. - Санкт-Петербург:
Питер, 2008. - 460 с.
3. ГОСТ 27.092-89. Надежность в технике. Основные понятия, термины и
определения.
4. Раздел упражнений от создателя языка Бьерна Страуструпа. - URL:http://
www.stroustmp.com/4thExercises.pdf 13.12.2019
5. Скотт Мейерс. Эффективное использование C++. 55 верных советов
улучшить структуру и код ваших программ [Текст] Мейерс Скотт. -
Москва: ДМК пресс, 2017. - 300 с.
Учебное издание

БЕЛЯКОВ Станислав Леонидович


БОЖ ЕНЮ К Александр Витальевич
ПЕТРЯЕВА Мария Владимировна

ОСНОВЫ РАЗРАБОТКИ ПРОГРАММ


НА ЯЗЫКЕ C++ ДЛЯ СИСТЕМ
ИНФОРМАЦИОННОЙ БЕЗОПАСНОСТИ

Учебное пособие

Редакторы: 3. И. Надточий, Н. И. Селезнева


Корректор Л. В. Чиканенко
Компьютерная верстка И. А. Клочко

Подписано в печать 26.01.2021 г.


Бумага офсетная. Формат 60x84 Vіб. Уел. печ. лист. 8,84.
Уел. изд. л. 4,51. Тираж 30 экз. Заказ № 7947.
Издательство Южного федерального университета
Отпечатано в отделе полиграфической, корпоративной и сувенирной продукции
Издательско-полиграфического комплекса КИБИ МЕДИА ЦЕНТРА ЮФУ
344090, г. Ростов-на-Дону, пр. Стачки 200/1. Тел. (863)243-41-66.

Вам также может понравиться