close

Вход

Забыли?

вход по аккаунту

?

InFORMATIKA ShPOR

код для вставкиСкачать
Билет №1
Этапы развития информатики и вычислительной техники.
ЭВМ - это сложная система, включающая как технические средства, так и программное обеспечение. Развитие аппаратных средств вычислительной техники можно условно разбить на несколько этапов, которые имеют свои характерные особенности. Первый этап - до 55г. Началом принимается 1946 год, когда началась опытная эксплуатация первых опытных образцов вычислительных машин. Данные о первых из них: общая масса - 30 тонн, число электронных ламп - 18 тыс., потребляемая мощность - 150 кВт, объем памяти - 20 10-ти разрядных чисел. Числа в ЭВМ вводились с помощью перфокарт и набора переключателей, а программа задавалась соединением гнезд на специальных наборных платах. Ламповые ЭВМ имели большие габариты и массу, потребляли много энергии и были очень дорогостоящими, что резко сужало круг пользователей ЭВМ, а, следовательно, объем производства этих машин. Увеличению количества решаемых задач препятствовали низкая надежность, ограниченность их ресурсов и чрезвычайно трудоемкий процесс подготовки, ввод и отладка программ, написанных на языке машинных команд.Повышение быстродействия ЭВМ шло за счет увеличения ее памяти и использование двоичных кодов для представления чисел и команд. Для ускорения процесса подготовки программ стали создавать первые языки автоматизации программирования. Представителями первых ЭВМ являлись ЭНИАК (США) и МЭСМ (СССР).
Второй этап - до 65 года. Изобретение полупроводникового устройства - транзистора, который заменил лампы. Появление ЭВМ, построенных на транзисторах, привело к уменьшению их габаритов, массы, энергозатрат и стоимости, а также к увеличению их надежности и производительности. Стали создавать алгоритмические языки для инженерно-технических и экономических задач.Для решения обеспечения экономии машинных ресурсов стали создавать операционные системы (комплексы служебных программ, обеспечивающих лучшее распределение ресурсов ЭВМ при использовании пользовательских задач).Вместе с программой и данными в ЭВМ вводится еще и инструкция, где перечисляются этапы обработки, и приводится ряд сведений о программе и ее авторе. Затем в ЭВМ стали вводить сразу по несколько заданий пользователей, ОС стали распределять ресурсы ЭВМ между этими заданиями - появился мультипрограммный режим обработки.
Третий этап - до 70 г. Увеличение быстродействия и надежности полупроводниковых схем, уменьшения их габаритов, потребляемой мощности и стоимости удалось добиться за счет создания технологии производства интегральных схем (ИС), состоящих из десятка электронных элементов. Это позволило не только повысить производительность и снизить стоимость больших ЭВМ, но и создать малые, простые, дешевые и надежные машины-мини-ЭВМ (СМ-1420). Простота обслуживания мини-ЭВМ, их сравнительно низкая стоимость и малые габариты позволяли снабдить этими машинами небольшие коллективы исследователей, разработчиков- экспериментаторов и т.д. Четвертый этап - до 78 г. Успехи в развитии электроники привели к созданию больших интегральных схем (БИС), где в одном кристалле размещалось несколько десятков тысяч электронных элементов. Это позволило разработать более дешевые ЭВМ, имеющие большую память и меньший цикл выполнения команд. Разрабатывались новые ОС, позволяющие программистам отлаживать свои программы прямо за дисплеем ЭВМ и ускоряло разработку программ. В 71 году был изготовлен первый микропроцессор - БИС, в которой полностью размещался процессор ЭВМ простой архитектуры. Появились дешевые микрокалькуляторы и микроконтроллеры - управляющие устройства, построенные на одной или нескольких БИС, содержащих процессор, память и системы связи с датчиками и исполнительными органами в объекте управления. Программа управления объектами вводилась в память ЭВМ либо при изготовлении, либо непосредственно на предприятии.Представители этого поколения ЭВМ: СМ-1800, "Электроника 60М".
Пятый этап - н/в. Улучшение технологии БИС позволяло изготовлять дешевые электронные схемы, содержащие сотни тысяч элементов в кристалле - схемы сверхбольшой степени интеграции - СБИС.Появилась возможность создать настольный прибор с габаритами массового телевизора, в котором размещались микро-ЭВМ, клавиатура, а также схемы сопряжения с малогабаритным печатающим устройством, измерительной аппаратурой, другими ЭВМ и т.п. Благодаря ОС, обеспечивающей простоту общения с этой ЭВМ такой персональный компьютер становится принадлежностью любого специалиста.
Билет№2
Структура и основные элементы персональной ЭВМ.
Обычно персональный компьютер состоит из трех частей:
· системного блока;
· клавиатуры, позволяющей вводить символы в компьютер;
· монитора (или дисплея) - для изображения текстовой или графической информации.
Компьютеры выпускаются и в портативном варианте (как дипломат) или блокнотном (ноутбук) исполнении. Здесь системный блок, монитор и клавиатура заключены в один корпус: системный блок "спрятан" под клавиатурой, а монитор сделан как крышка к клавиатуре.
Хотя из этих частей компьютера системный блок выглядит наименее эффектно, именно он является в компьютере "главным". В нем располагаются все основные узлы компьютера:
· электронные схемы, управляющие работой компьютера (микропроцессоры, оперативная память, контроллеры устройств);
· блок питания, преобразующий электропитание сети в постоянный ток низкого напряжения, подаваемый на электронные схемы компьютера;
· накопители (или дисководы) для гибких магнитных дисков, используемые для чтения и записи на гибкие магнитные диски (дискеты);
· накопитель на жестких магнитных дисках, предназначенные для чтения и записи на несъемные жесткие магнитные диски (винчестер).
Микропроцессор - важнейший элемент компьютера, так как им определяется скорость выполнения машиной программ пользователя. Со времени появления персональных компьютеров (ПК) сменилось несколько поколений процессоров, что составляет следующий ряд в порядке увеличения скорости: 8088, 286, 386SX, 386DX, 486SX, 486DX, 486DX2, Pentium, Pentium Pro и другие.
Параметры процессора:
· разрядность - ширина "такта", по которому передается компьютерная информация: 8, 16, 32 или 64 бита;
· тактовая частота, характеризующая число команд, выполняемых процессором за одну секунду (измеряется в мегагерцах (МГц)). Обычно тактовая частота соответствует 160...200МГц.
Микропроцессор включает в себя:
· арифметико-логическое устройство (АЛУ), которое выполняет операции (микрооперации), необходимые для выполнения команд микропроцессора;
· устройство управления (УУ) - управляет всеми частями компьютера посредством принципов программного управления;
· микропроцессорная память (МПП). В микропроцессоре есть несколько ячеек собственной памяти, они называются регистрами. Некоторые из них предназначены для хранения операндов - величин, участвующих в текущей операции. Такие регистры называются регистрами общего назначения (RON).
Регистр команд (RK) предназначен для хранения текущей команды. В регистре - счетчике команд (СК) хранится текущий адрес. Перед выполнением программы необходимо задать ее начальный адрес - записать его в счетчик команд.
Через интерфейсную систему, основу которой составляет системная шина персонального компьютера, микропроцессор соединяется с:
а) Основной памятью компьютера:-оперативное запоминающее устройство (RAM) хранит работающую программу и данные;- постоянное запоминающее устройство (ROM) - хранит информацию, которая необходима для постоянной работы.
RAM и ROM разбиты на ячейки, каждой из которых присвоен порядковый номер (адрес).
б) Внешней памятью:
- накопители на жестких магнитных дисках - устройства с несъемными носителями (винчестеры). Жесткие диски служат для постоянного хранения в компьютере программ и данных.
Выполнение многих современных прикладных программ без них невозможно. Большинство жестких дисков, в отличие от имеющих меньшую емкость дискет, нельзя снять, поэтому их иногда называют несъемными дисками. Можно, однако приобрести и съемные жесткие диски. Они ценны, когда нужно сохранять конфиденциальность информации и как средство переноса больших объемов данных между компьютерами. Емкость современных накопителей на жестких магнитных дисках может достигать нескольких Гбайт.
Более популярны становятся накопители на оптических дисках благодаря большой емкости и надежности.
Неперезаписываемые лазерно-оптические диски обычно называют компакт-дисками ПЗУ - Compact disc (CD) ROM. Они имеют емкость до 1,5Гбайт, время доступа - от 30 до 300мс.
- накопители на гибких магнитных дисках. Для данных накопителей носителями являются дискеты (флоппи-диски).
в) С монитором через видеоадаптер.
г) С принтером через адаптер принтера.
д) С источником питания.
ж) С каналом связи через сетевой адаптер.
Сетевой адаптер дает возможность подключить компьютер в локальную сеть. При этом пользователь может получать доступ к данным, находящимся на других компьютерах.
з) С таймером (таймер - внутренние электронные часы, которые подключены к автономному источнику питания (аккумулятору), продолжающий работать даже после отключения машины от питающей сети).
и) Микропроцессор через интерфейс связан с клавиатурой, а также имеет генератор тактовых импульсов, который генерирует последовательность электрических импульсов, а частота этих импульсов определяет тактовую частоту машины (ее быстродействие).
к) С математическим сопроцессором.
Обычно универсальные микропроцессоры относительно медленно выполняют арифметические операции над числами с плавающей запятой. Это объясняется тем, что они работают с целыми числами, и при использовании чисел, представленных в другой форме, им требуются дополнительные команды преобразования.
Для ускорения выполнения арифметических операций часто используется отдельный процессор, называемый математическим сопроцессором. Он выполняет арифметические операции над числами с плавающей запятой самостоятельно, без дополнительных программных средств. Благодаря этому в несколько раз возрастает скорость вычислительного процесса.
Билет №3
Системы счисления.
Система счисления - символический метод записи чисел, представление чисел с помощью письменных знаков.Число - это некоторая абстрактная сущность для описания количества.Цифры - это знаки, используемые для записи чисел.
Цифры бывают разные: самыми распространёнными являются арабские цифры, представляемые известными нам знаками от 0 до 9; менее распространены римские цифры, мы их можем иногда встретить на циферблате часов или в обозначении века (XIX век).
Системы счисления разделить на три класса: позиционные; непозиционные; смешанные.
смешанные и непозиционные системы: Денежные знаки - это пример смешанной системы счисления.Примером "чисто" непозиционной системы счисления является римская система.
Позиционные системы счисления - это системы счисления, в которых значение цифры напрямую зависит от её положения в числе.
Например, число 01 обозначает единицу, 10 - десять.Позиционные системы счисления позволяют легко производить арифметические расчёты.Представление чисел с помощью арабских цифр - самая распространённая позиционная система счисления, она называется "десятичной системой счисления". Для составления машинных кодов удобно использовать не десятичную, а двоичную систему счисления, содержащую только две цифры, 0 и 1. Обратите внимание, что в двоичной системе максимальная цифра 1.Программисты для вычислений также пользуются ещё восьмеричной и шестнадцатеричной системами счисления.
Зависимость плотности записи информации от основания системы счисления
Плотность информации в записи числа зависит от основания системы счисления х и выражается функцией y=(ln(x))/x.
Эта функция имеет максимум при x=e=2,718281828.... Т.е. система счисления с наибольшей плотностью записи имеет нецелочисленное основание!Из целых чисел ближайшее к числу е - это число 3.Поэтому из целочисленных систем счисления наибольшей плотностью записи информации обладает троичная система счисления, т.е. система с основанием равным трём.
Билет №4
Основные понятия операционной системы
Операционная система (ОС) - комплекс системных и управляющих программ, предназначенных для наиболее эффективного использования всех ресурсов вычислительной системы (ВС) (Вычислительная система - взаимосвязанная совокупность аппаратных средств вычислительной техники и программного обеспечения, предназначенная для обработки информации) и удобства работы с ней. Назначение ОС - организация вычислительного процесса в вычислительной системе, рациональное распределение вычислительных ресурсов между отдельными решаемыми задачами; предоставление пользователям многочисленных сервисных средств, облегчающих процесс программирования и отладки задач. Операционная система исполняет роль своеобразного интерфейса ( Интерфейс - совокупность аппаратуры и программных средств, необходимых для подключения периферийных устройств к ПЭВМ) между пользователем и ВС, т.е. ОС предоставляет пользователю виртуальную ВС. Это означает, что ОС в значительной степени формирует у пользователя представление о возможностях ВС, удобстве работы с ней, ее пропускной способности. Различные ОС на одних и тех же технических средствах могут предоставить пользователю различные возможности для организации вычислительного процесса или автоматизированной обработки данных. В программном обеспечении ВС операционная система занимает основное положение, поскольку осуществляет планирование и контроль всего вычислительного процесса. Любая из компонент программного обеспечения обязательно работает под управлением ОС. В соответствии с условиями применения различают три режима ОС: пакетной обработки, разделения времени и реального времени. В режиме пакетной обработки ОС последовательно выполняет собранные в пакет задания. В этом режиме пользователь не имеет контакта с ЭВМ, получая лишь результаты вычислений. В режиме разделения времени ОС одновременно выполняет несколько задач, допуская обращение каждого пользователя к ЭВМ. В режиме реального времени ОС обеспечивает управление объектами в соответствии с принимаемыми входными сигналами. Время отклика ЭВМ с ОС реального времени на возмущающее воздействие должно быть минимальным.
Билет №5
Основные элементы, цели программирования.
Цель программирования - создать хорошую программу, т.е. программу, которая: а) надежна, т.е. зависит только от своих действий; б) универсальна, т.е. ее можно легко изменить, когда нужна переделка; в) совместима, т.е. ее можно перенести с одного компьютера на другой с минимальными изменениями; г) удобочитаема, т.е. хорошо понимаема пользователем; д) эффективна, т.е. реализует наиболее эффективный способ решения задачи. ЭТАПЫ ПРОГРАММИРОВАНИЯ:
1)Понимание условия задачи. Программист нуждается в точном описании того, что требуется сделать, и как должна работать программа. Это описание должно быть представлено в системной спецификации, содержащей входные данные, этапы процесса выполнения работы и выходные данные. 2) Планирование метода решения зависит от размера задачи. В подготовке программы могут участвовать несколько программистов, а работа коллектива людей требует общего плана работы. Большие программы требуют от каждого программиста написания отдельных частей программы. Эта отдельная часть программы называется модулем или сегментом. Модули могут подготавливаться и тестироваться отдельно, затем, оттестированные, соединяться в одно целое. 3) Разработка структуры данных, методов программирования и алгоритмов с использованием блок - схем, таблиц, псевдокода. Сложные проблемы могут быть решены простыми методами, если они разбиты на множество более простых задач. Каждую подзадачу разбивают на более мелкие и уже в деталях размышляют над ее решением. Этот общий подход называется программированием сверху вниз ( нисходящее программирование). 4) Написание программы на языке программирования. Это последний шаг при нисходящем программировании . В качестве исходных данных берутся команды, которые затем переписываются на языке программирования. 5) Тестирование программы. С помощью тестов можно выявить ошибки. Это очень длинный и дорогой процесс. Внимательность и основательный подход к решению задачи на ранней стадии разработки программы могут уменьшить количество ошибок. 6). Составление документации, содержащей описание всей работы, проделанной в процессе разработки программы - очень важный этап работы программиста. Документация включает в себя : постановку задачи (системная спецификация), алгоритм решения, набор тестов, управляющие команды (руководство) пользователя и т.д. Подготовка соответствующей документации - завершающая часть каждого этапа программирования и никак не должна выполняться после завершения всей работы.
Билет №6
Основы программирования в редакторе С++.
Объектно-ориентированное программирование - это самый высокоуровневый вид программирования в настоящее время. Здесь поддерживаются достижения предыдущих поколений и добавлены новые свойства. Эти новые свойства реализуют парадигму объектно-ориентированного программирования.
Объектно-ориентированное программирование на C++ основывается на следующих основных этапах разработки программ.
Первый этап заключается в выделении абстракций. Выделение абстракций означает анализ предметной области, для которой составляется программа, с целью определения основных объектов предметной области, их свойств, отношений между объектами, а также возможных операций над объектами и их составляющими.
Второй этап состоит в типизации объектов и синтезе абстрактных типов данных.
Этап предполагает определение новых производных типов данных и наборов специфических функций или операций, применяемых к этим типам данных таким образом, чтобы исключить возможность смешивания или взаимозамены различных типов.
Третий этап заключается в объектной декомпозиции как выделении подтипов или подобъектов и их составляющих для каждого из типов объектов.
Четвертый этап представляет собой композиционную иерархизацию объектов как выделение родовидовых и композиционных отношений над объектами.
В результате объектно-ориентированного подхода к проектированию программ процесс разработки программы превращается в процесс эволюционного программирования, который для внесения каких-либо изменений и дополнений в программу не требует кардинального пересмотра составляющих ее алгоритмов. Эволюционный способ программирования опирается на сохранение целостности объектов программы, то есть внесение изменений в программу не должно затрагивать внутреннюю организацию существующих в ней объектов.
Важным свойством объектно-ориентированных языков является возможность разработки на них программ, работающих в системах со сложными параллельными вычислительными процессами, изначально присущими техническим средствам вычислительной техники. Это свойство опирается на концепцию активных и неактивных объектов в период функционирования программы. Одновременная активность различных объектов становится возможной за счет их строгой типизации и закрытости для изменений другими объектами.
Язык программирования C++ обладает всеми основными свойствами языков объектно-ориентированного программирования и существенно отличается по своей концепции от базового языка C.
Существует несколько принципов, лежащих в основе языка C++:
1. Инкапсуляция - это объединение производного типа данных с набором функций, используемых при работе с этим типом, в единый класс. При этом функции, включенные в класс, называются методами класса, данные - элементами данных, а конкретные представители класса - объектами класса. Закрытие данных и методов оперирования этими данными происходит таким образом, чтобы обращаться можно было бы только определенным объектам (в данном случае только объектам этих типов).
2. Наследование - это способность одних классов заимствовать основные свойства других классов, в частности - методы классов и элементы данных. Класс, наследующий свойства, называют производным, а класс, предоставляющий свои свойства для наследования, - базовым. Механизм наследования позволяет создавать иерархию классов, то есть многоуровневую систему классов, связанных между собой отношением наследования.
3. Полиморфизм - это возможность определения функции, работающей с различными по типу данных списками параметров в пределах какого-либо одного вида алгоритмов. Такие функции называются обычно виртуальными и проектируются как некоторое семейство одноименных функций, работающих с различными типами данных. Механизм, реализующий выбор какой-либо конкретной функции из определенного семейства, носит название механизма позднего связывания, поскольку может быть использован в процессе выполнения готовой программы
Билет №7
Алфавит и ключевые слова
Алфавит языка С++ состоит из следующих символов и их наборов:
латинские буквы
цифры
специальные символы + - * / {} . , ; : ' " & | % = > < ( ) [ ] ! # ( )
составные символы, каждый из которых рассматривается как один символ: == != >= <= /* */ && || %= &= ++ -- += *= -= /= :: .* -> ->* ... << <<= >> >>=
Буквы кириллицы в C++ допустимы только внутри строк и комментариев.
Ключевые слова
Как и в любом языке программирования, в С++ существует набор ключевых слов для обозначения управляющих структур, директив и т.д. Вот этот набор:asm auto break case char class const continue default delete do double else enum extern float for friend goto if inline int long new operator overload public register return short sizeof static struct switch this typedef union unsigned virtual void while
Билет №8
Const и переменные. Их типы.
Константы - неизменяемые величины. Различаются целые, вещественные, символьные и строковые константы. Компилятор, выделив константу в качестве лексемы, относит ее к одному из типов по ее внешнему виду.
Форматы констант, соответствующие каждому типу, приведены в табл. 1.2. Таблица 1.2. Константы в языке С++ Константа Формат Примеры
Целая Десятичный: последовательность десятичных цифр, начинающаяся не с нуля, если это не число нуль 8, 0, 199226 Восьмеричный: нуль, за которым следуют восьмеричные цифры (0,1,2,3,4,5,6,7) 01, 020, 07155 Шестнадцатеричный: 0х или 0Х, за которым следуют шестнадцатеричные цифры (0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F) 0xA, 0x1B8, 0X00FF Вещественная Десятичный: [цифры].[цифры] 5.7, .001, 35. Экспоненциальный: [цифры][.][цифры]{E|e}[+|-][цифры] 0.2E6, .11e-3, 5E10 Символьная Один или два символа, заключенных в апострофы 'A', 'ю', '*', 'db', '\0', '\n', '\012', '\x07\x07' Строковая Последовательность символов, заключенная в кавычки "Здесь был Vasia", "\tЗначение r=\0xF5\n" Допустимые диапазоны значений целых и вещественных констант приведены в табл. 1.4. Если требуется сформировать отрицательную целую или вещественную константу, то перед константой ставится знак унарной операции изменения знака (-), например: -218, -022, -0x3С, -4.8, -0.1e4. Вещественная константа в экспоненциальном формате представляется в виде мантиссы и порядка. Мантисса записывается слева от знака экспоненты (E или e), порядок - справа от знака. Значение константы определяется как произведение мантиссы и возведенного в указанную в порядке степень числа 10. Обратите внимание, что пробелы внутри числа не допускаются, а для отделения целой части от дробной используется не запятая, а точка. Символьные константы, состоящие из одного символа, занимают в памяти один байт и имеют стандартный тип char. Двухсимвольные константы занимают два байта и имеют тип int, при этом первый символ размещается в байте с меньшим адресом (о типах данных рассказывается в следующем разделе). Символ обратной косой черты используется для представления: кодов, не имеющих графического изображения (например, \a - звуковой сигнал, \n - перевод курсора в начало следующей строки); символов апострофа ( ' ), обратной косой черты ( \ ), знака вопроса ( ? ) и кавычки ( " ); любого символа с помощью его шестнадцатеричного или восьмеричного кода, например, \073, \0xF5. Числовое значение должно находиться в диапазоне от 0 до 255. Последовательности символов, начинающиеся с обратной косой черты, называют управляющими, или escape-последовательностями. В таблице 1.3 приведены их допустимые значения. Управляющая последовательность интерпретируется как одиночный символ. Если непосредственно за обратной косой чертой следует символ, не предусмотренный табл. 1.3, результат интерпретации не определен. Если в последовательности цифр встречается недопустимая, она считается концом цифрового кода. Таблица 1.3. Управляющие последовательности в языке С++ ИзображениеШестнадцатеричный код Наименование
\a 7 Звуковой сигнал
\b 8 Возврат на шаг \f C Перевод страницы (формата) \n A Перевод строки \r D Возврат каретки \t 9 Горизонтальная табуляция \v B Вертикальная табуляция \\ 5C Обратная косая черта \' 27 Апостроф \" 22 Кавычка \? 3F Вопросительный знак \0ddd - Восьмеричный код символа \0xddd ddd Шестнадцатеричный код символа Управляющие последовательности могут использоваться и в строковых константах, называемых иначе строковыми литералами. Например, если внутри строки требуется записать кавычку, ее предваряют косой чертой, по которой компилятор отличает ее от кавычки, ограничивающей строку: "Издательский дом \"Питер\""
Все строковые литералы рассматриваются компилятором как различные объекты. Строковые константы, отделенные в программе только пробельными символами, при компиляции объединяются в одну. Длинную строковую константу можно разместить на нескольких строках, используя в качестве знака переноса обратную косую черту, за которой следует перевод строки. Эти символы игнорируются компилятором, при этом следующая строка воспринимается как продолжение предыдущей. Например, строка
"Никто не доволен своей \
внешностью, но все довольны \
своим умом"
полностью эквивалентна строке "Никто не доволен своей внешностью, но все довольны своим умом" В конец каждого строкового литерала компилятором добавляется нулевой символ, представляемый управляющей последовательностью \0. Поэтому длина строки всегда на единицу больше количества символов в ее записи. Таким образом, пустая строка "" имеет длину 1 байт. Обратите внимание на разницу между строкой из одного символа, например, "A", и символьной константой 'A'. Пустая символьная константа недопустима.
Переменные - это кусок памяти компьютера, хранящий последовательность 0 и 1. Сам по себе, процессор не знает, что вы храните: дату вашего рождения, номер паспорта или красивую фото. Для него все это 1 0 1 0 0 0 1 ... Поэтому, программе надо знать, что она хранит в памяти и как с этим работать. Для этого и существуют типы данных.
Основные типы данных в c++:
int (signed int) - целое число со знаком размером 4 байта. Находится в промежутке от -2,147,483,648 до 2,147,483,647
unsigned int - целое не отрицательное число размером 4 байта. В промежутке от 0 до 4,294,967,295
long long - целое число от -9,223,372,036,854,775,808 до 9,223,372,036,854,775,807
float - десятичная дробь. Размер 4 байта
double - тоже десятичная дробь, но размером в 2 байта
short - целое число от -32,768 до 32,767
unsigned short - целое число от 0 до 65,535
bool - "булевая" переменная. Эта переменная, хранящая всего одно из 2х значений: правда или ложь (1 или 0)
char - символьная переменная размеров в 1 байт. Хранит одни символ, а точнее его код в заданной кодировке.
Билет №9
Выражения и операции. Операторы описания.
В С++ имеется большое число операций, и они будут объясняться там, где (и если) это потребуется. Следует учесть, что операции
~ (дополнение) amp; (И) ^ (исключающее ИЛИ) ! (включающее ИЛИ) "" (логический сдвиг влево) "" (логический сдвиг вправо)
применяются к целым, и что нет отдельного типа данных для логических действий.
Смысл операции зависит от числа операндов. Унарное amp; является операцией взятия адреса, а бинарное amp; - это операция логического И. Смысл операции зависит также от типа ее операндов: + в выражении a+b означает сложение с плавающей строкой, если операнды имеют тип float, но целое сложение, если они типа int. В #1.8 объясняется, как можно определить операцию для типа, определяемого пользователем, без потери ее значения, предопределенного для основных и производных типов.
В С++ есть операция присваивания =, а не оператор присваивания, как в некоторых языках. Таким образом, присваивание может встречаться в неожиданном контексте, например, x=sqrt(a =3*x). Это бывает полезно. a=b=c означает присвоение c объекту b, а затем объекту a. Другим свойством операции присваивания является то, что она может совмещаться с большинством бинарных операций. Например, x[i+3]*=4 означает x[i+3]=x[i+3]*4, за исключением того факта, что выражение x[i +3] вычисляется только один раз. Это дает привлекательную степень эффективности без необходимости обращения к оптимизирующим компиляторам. К тому же это более кратко.
В большинстве программ на С++ широко применяются указатели. Унарная операция * разыменовывает* указатель, т.е. *p есть объект, на который указывает p. Эта операция также называется косвенной адресацией. Например, если имеется char* p, то *p есть символ, на который указывает p. Часто при работе с указателями бывают полезны операция увеличения ++ и операция уменьшения -. Предположим, p указывает на элемент вектора v, тогда p++ делает p указывающим на следующий элемент.
- * англ. dereference - получить значение объекта, на который указывает данный указатель. (прим. перев.)
Операторы Выражения
Самый обычный вид оператора - выражение;. Он состоит из выражения, за которым следует точка с запятой. Например:
a = b*3+c; cout "" "go go go"; lseek(fd,0,2);
Описание - это оператор, вводящий имя в программе. Оно может также инициализировать объект с этим именем. Выполнение описания означает, что когда поток управления доходит до описания, вычисляется инициализирующее выражение (инициализатор) и производится инициализация. Например:for (int i = 1; i"MAX; i++) (* int t = v[i-1]; v[i-1] = v[i]; v[i] = t; *)
При каждом выполнении оператора for i будет инициализироваться один раз, а t MAX-1 раз.
Билет №13
Статические массивы. Объявление массивов.
массивы - это упорядоченная последовательность, имеющая общее имя. Это общее понятие массива, хочется заметить, что массивы бывают статические и динамические. Массив имеет фиксированное число членов. Динамический массив может менять число членов в течение выполнения программы.
Сверху идут индексы массива, а снизу элементы.
После рассмотрения общей теории по массивам, рассмотрим уже конкретно по языку программирования С.
Синтаксис массива в языке программирования С
Для начала посмотрим, как описывается массив на языке С.
<тип элементов массива> идентификатор (имя массива) [размерность массива];
Вот так выглядит описание массива в общем виде, теперь расскажу подробнее. Сначала вы указываете тип данных, который имею все элементы массива (это важно, что все элементы массива должны быть одного типа. Например, в целочисленный массив вы не можете добавить строку в качестве элемента). Идентификатор - это то, как будет называться массив в вашей программы, то же самое что имя и обычной переменной. Размерность массива - это то количество элементов, которое может иметь ваш массив. Нумерация элементов массива начинается с 0, поэтому в качестве размерности нужно указывать число n-1, где n-количество элементов в массиве. Напомню, что в статическом массиве число элементов постоянно в течение выполнения всей программы, и поэтому в качестве размерности массива может быть либо целое число, либо константное выражение целого типа данных.
Обращаются к элементам массива следующим образом: имя массива [номер элемента]; где номер элемента это целое число или переменная, причем небольшие, чем n-1, где n - количество элементов массива.
Теперь мы узнали, как объявлять массив и как обращаться к его элементам, но мы еще не можем использовать их в программе, пока мы не узнаем несколько алгоритмов для работы с массивами и начнем мы с заполнения и вывода массива.
Заполнение и вывод массива
Заполнение и вывод массива выполняется похожим образом. Я прокомментирую и то и другое, чтобы вы увидели эту схожесть, хотя логикой понятно, что это просто взаимообратные процессы. Заполнять массив можно несколькими способами:
1. Самый нерекомендуемый, но иногда применяемый способ - заполнение массива вручную, то есть вид a[1]=x1; a[2]=x2, a[3]=x3 ... a[n-1]=xn_m1, то есть вы в коде даете элементам массива значения, которые придумываете сами (значения должны совпадать с типом элементов массива)
2. Заполнение с клавиатуры - это заполнение идет чаще всего циклом, но пользователь с клавиатуры вводит значения элементов массива. Вот так это будет выглядеть for(int i=0;i<n;i++) scanf("%i",&a[i]); В этом примере у нас есть одномерный целочисленный массив a размерности n и цикл, идущий от 0 до n-1, и оператор scanf, про который вы можете найти в уроке "Основные элементы языка С", который считывает с клавиатуры элементы массива.
3. Заполнение случайными числами - заполнение массива идет чаще всего циклами, но дополнительно используются функции rand и srand, которые вы найдете в библиотеке stdio.h
Мы рассмотрели способы ввода массивов, способы вывода абсолютно такие же только везде вместо scanf нужно писать printf и не ставить &.
Теперь мы смогли заполнить массив, но нам нужно произвести с ним какие-либо действия, я покажу такие действия: нахождение максимума и минимума, нахождение суммы и произведения элементов массива и подсчет элементов массива, удовлетворяющих определенному условию. Сортировки и перестановки в массивах достойны отдельного урока.
Нахождение максимального и минимального элемента в массиве
Алгоритм нахождение максимального (минимального) элемента массива прост. Для начала мы берем гипотезу, что первый элемент максимальный, а затем сравниваем все элементы массива с максимумом, если встречен элемент больше максимума, то максимумом становиться тот элемент, и продолжаем сравнивание элементов с новым максимумом. Точно также находится и минимальный элемент массива. Все коды программ вы найдете в примерах, а здесь объясняется только принцип.
Нахождение суммы и произведения элементов массива
Тут, казалось бы, все просто складывай или перемножай себе элементы массива без разбору и все нормально будет, но на самом деле все не так просто. Я тут хочу обратить внимание на два нюанса, а все остальное действительно просто, умножай или складывай. Первое о чем я хочу сказать, перед нахождением суммы переменная, в которой это сумма храниться должна быть равна 0, а переменная, в которой храниться произведение должна быть равна 1, так как любое число, умноженное на 0, будет 0. Второе и очень важное, надо следить, чтобы переменная не вышла за диапазон значений, отдающийся под ее тип данных, часто бывает необходимым использовать типы long , это касается и суммы и произведения, особенно произведения.
Подсчет элементов массива, удовлетворяющих определенному условию
На самом деле тут ничего сложного нет. Надо просто завести еще одну переменную-счетчик, которая изначально равна 0, затем просматривать все элементы массива, и если данный элемент удовлетворяет условию, приведенному в задаче, то увеличивать эту переменную на 1.
Примеры
1.найти номер максимального элемента массива.
#include<stdio.h>
#include<stdlib.h>
int main()
{
const int n=10;
int nArray[n];
//заполнение массива
for(int i=0;i<n;i++)
scanf("%i",&nArray[i]);
//инициализация номера максимального элемента и максимального элемента
int nMax=0, nNuberofMax=nArray[0];
//поиск максимального элемента и его номера
for(int i=0;i<n;i++)
if(nArray[i]>nMax)
{
nMax=nArray[i];
nNumberofMax=i;
}
//вывод номера максимального элемента
printf("%i",nNumberofMax);
return 0;
}
Билет №14
Динамические массивы. Объявление массивов.
Во всех вышеприведенных примерах объявлялись статические массивы, поскольку нижняя граница равна нулю по определению, аверхняя всегда задавалась в этих примерах константой. Напомню, что в C# все массивы, независимо от того, каким выражением описывается граница, рассматриваются как динамические, и память для них распределяется в "куче". Полагаю, что это отражение разумной точки зрения: ведь статические массивы, скорее исключение, а правилом является использование динамических массивов. В действительности реальные потребности в размере массива, скорее всего, выясняются в процессе работы в диалоге с пользователем.
Чисто синтаксически нет существенной разницы в объявлении статических и динамических массивов. Выражение, задающее границу изменения индексов, в динамическом случае содержит переменные. Единственное требование - значения переменных должны быть определены в момент объявления. Это ограничение в C# выполняется автоматически, поскольку хорошо известно, сколь требовательно C# контролирует инициализацию переменных.
Приведу пример, в котором описана работа с динамическим массивом:
public void TestDynAr()
{
//объявление динамического массива A1
Console.WriteLine("Введите число элементов массива A1");
int size = int.Parse(Console.ReadLine());
int[] A1 = new int[size];
Arrs.CreateOneDimAr(A1);
Arrs.PrintAr1("A1",A1);
}//TestDynAr
Билет №15
Адреса и ссылки. Ссылки
Гипертекстовый документ - это документ, содержащий ссылки на другие документы, позволяющие при помощи нажатия кнопки мыши быстро перемещаться от одного документа к другому. Часто подобные ссылки можно увидеть и в файлах справки программных продуктов.
Гипермедийный документ - основан на гипертекстовом документе, но в дополнение к тексту содержит разнообразную графику, видео- и аудиообъекты. В таких документах в качестве ссылок часто используются изображения. Существует очень много типов мультимедийных объектов, которые могут быть размещены на Web - странице.
Ссылка состоит из двух частей. Первая из них - это то, что вы видите на странице; она называется указатель (anchor). Вторая часть, дающая инструкцию браузеру, называется адресной частью ссылки (URL - адресом, URL reference). Когда вы щелкаете мышью по указателю ссылки, браузер загружает документ, адрес которого определяется URL - адресом. Составные части ссылки рассмотрены ниже.
В языке C++ появился новый механизм работы с переменными - ссылки. Функция swap() была хороша, только не слишком удобно применять разыменование. С помощью ссылок функция swap() может выглядеть аккуратнее.
#include void swap(double& a, double& b) {
double temp = a;
a = b;
b = temp;
}
А вызов функции тогда будет уже без взятия адреса переменных.
swap(x, y);
Конструкция double& объявляет ссылку на переменную типа double. При таком объявлении функции в стек будут положены не значения переменных, а их адреса.
Ссылка - это указатель, с которым можно работать, как с обычной переменной.
Ссылка не может быть равна NULL. Указатель может. Ссылка не может быть непроинициализирована. Указатель может.
Для взятия адреса переменной и для объявления ссылки используется одинаковый символ - амперсанд. Но в случае взятия адреса & стоит в выражении, перед именем переменной. А в случае объявления ссылки - в объявлении, после объявления типа.
Адрес переменной и значение переменной по адресу
Второй частью ссылки является URL - адрес. Это не что иное, как адрес Web - страницы, которая будет загружена, если щелкнуть на указателе ссылки кнопкой мыши. Указание адреса может быть относительным или абсолютным:
Относительные указатели. URL - адрес файла, расположенный на том же компьютере, что и документ, в котором находится указатель этой ссылки, называется относительным. Это означает, что если браузер загрузил страницу, находящуюся по адресу http://www.mysite.com/page, то относительный адрес /picture подразумевает адрес http://www.mysite.com/page/picture, т.е. подкаталог, расположенный на той же машине. Относительные адреса удобны в использовании. Намного проще вставить только имя файла, а не весь длинный URL - адрес. Они также позволяют перемещать файлы в пределах сервера без больших изменений в межстраничной адресации.
Абсолютные указатели. URL - адрес, полностью определяющий компьютер, каталог и файл, называется абсолютным. В отличие от относительных адресов, абсолютные могут ссылаться на файлы, расположенные на других компьютерах.
Рассмотрим две переменные: целочисленную переменную x и указатель на целочисленную переменную.
int x;
int *p;
Чтобы получить адрес переменной, нужно перед ее именем написать амперсанд.
p = &x;
Данная конструкция будет выполняться справа налево. Сначала с помощью оператора &, примененного к переменной x, будет получен адрес x. Затем адрес x будет сохранен в указателе p.
Есть и обратная операция. Чтобы получить значение переменной по ее адресу, следует написать звездочку перед именем указателя.
int y = *p;
Такая операция в русском языке называется не слишком благозвучным словом "разыменование". В английском - dereference.
В данном примере с помощью оператора * мы получим то значение, которое находится в памяти по адресу p. Затем мы сохраним его в переменную y. В итоге получится, что значения x и y совпадают.
Все это несложно увидеть на экране.
#include int main(void) {
int x;
int y;
int *p;
x = 13;
y = 0;
p = &x;
y = *p;
printf("Value of x\t%d", x);
printf("Address of x\t%p", &x);
printf("\n");
printf("Value of p\t%p", p);
printf("Address of p\t%p", &p);
printf("\n");
printf("Value of y\t%d", y);
printf("Address of y\t%p", &y);
printf("\n");
return 0;
}
Билет №16
Динамическое выделение памяти.
Динамические объекты не имеют собственных имен, и действия над ними производятсякосвенно, с помощью указателей; · выделение и освобождение памяти под статические объекты производится компилятором автоматически.Выделение и освобождение памяти под статические объекты производится компилятором автоматически. Программисту не нужно самому заботиться об этом. Выделение и освобождение памяти под динамические объекты целиком и полностью возлагается на программиста. Это достаточно сложная задача, при решении которой легко наделать ошибок. Для манипуляции динамически выделяемой памятью служат операторы new и delete.
Оператор new имеет две формы. Первая форма выделяет память под единичный объект определенного типа:
int *pint = new int(1024);
Здесь оператор new выделяет память под безымянный объект типа int, инициализирует его значением 1024 и возвращает адрес созданного объекта. Этот адрес используется для инициализации указателя pint. Все действия над таким безымянным объектом производятся путем разыменовывания данного указателя, т.к. явно манипулировать динамическим объектом невозможно.
Вторая форма оператора new выделяет память под массив заданного размера, состоящий из элементов определенного типа:
int *pia = new int[4];
В этом примере память выделяется под массив из четырех элементов типа int. К сожалению, данная форма оператора new не позволяет инициализировать элементы массива.
Некоторую путаницу вносит то, что обе формы оператора new возвращают одинаковый указатель, в нашем примере это указатель на целое. И pint, иpia объявлены совершенно одинаково, однако pint указывает на единственный объект типа int, а pia - на первый элемент массива из четырех объектов типа int.
Когда динамический объект больше не нужен, мы должны явным образом освободить отведенную под него память. Это делается с помощью оператора delete, имеющего, как и new, две формы - для единичного объекта и для массива:
// освобождение единичного объекта
delete pint;
// освобождение массиваdelete[] pia;
Что случится, если мы забудем освободить выделенную память? Память будет расходоваться впустую, она окажется неиспользуемой, однако возвратить ее системе нельзя, поскольку у нас нет указателя на нее. Такое явление получило специальное название утечка памяти. В конце концов программа аварийно завершится из-за нехватки памяти (если, конечно, она будет работать достаточно долго). Небольшая утечка трудно поддается обнаружению, но существуют утилиты, помогающие это сделать.
Билет №17
Многомерные массивы.
Многомерные массивы в C++ рассматриваются как массивы, элементами которых являются массивы.
Определение многомерного массива должно содержать информацию о типе, размерности и количестве элементов каждой размерности.
int MyArray1[10]; // Одномерный массив размерности 10.
int MyArray2[20][10]; // 20 одномерных массивов размерности 10.
int MyArray3[30][20][10]; // 30 двумерных массивов размерности 20*10.
По крайней мере, для Borland C++ 4.5, элементы многомерного массива располагаются в памяти в порядке возрастания самого правого индекса, т.е. самый младший адрес имеют элементы
MyArray1[0],
MyArray2[0][0],
MyArray3[0][0][0],
затем элементы
MyArray1[1],
MyArray2[0][1],
MyArray3[0][0][1]
и т.д.
Многомерный массив подобно одномерному массиву может быть проинициализирован с помощью списка инициализаторов. Первыми инициализируются элементы с самыми маленькими индексами:
int MyArray[3][3][3] = {0,1,2,3,4,5,6,7,8,9,10,11};
Начальные значения получают следующие элементы трёхмерного массива:
MyArray[0][0][0] == 0
MyArray[0][0][1] == 1
MyArray[0][0][2] == 2
MyArray[0][1][0] == 3
MyArray[0][1][1] == 4
MyArray[0][1][2] == 5
MyArray[0][2][0] == 6
MyArray[0][2][1] == 7
MyArray[0][2][2] == 8
MyArray[1][0][0] == 9
MyArray[1][0][1] == 10
MyArray[1][0][2] == 11
Остальные элементы массива получают начальные значения в соответствии со статусом массива (в глобальном массиве значения остальных элементов равны 0, в локальном массиве элементам присваиваются неопределённые значения).
Дополнительные фигурные скобки в инициализаторе позволяют инициализировать отдельные фрагменты многомерного массива. Каждая пара фигурных скобок специфицирует значения, относящиеся к одной определённой размерности. Пустые фигурные скобки не допускаются (и это означает, что в C++ реализован жёсткий алгоритм инициализации массивов):
int MyArray[3][3][3] = {
{{0,1}},
{{100},{200,210},{300}},
{{1000},{2000,2100},{3000,3100,3200}}
};
В результате выполнения этого оператора определения будут означены следующие элементы массива MyArray:
MyArray[0][0][0] == 0
MyArray[0][0][1] == 1
MyArray[1][0][0] == 100
MyArray[1][1][0] == 200
MyArray[1][1][1] == 210
MyArray[1][2][0] == 300
MyArray[2][0][0] == 1000
MyArray[2][1][0] == 2000
MyArray[2][1][1] == 2100
MyArray[2][2][0] == 3000
MyArray[2][2][1] == 3100
MyArray[2][2][2] == 3200
По аналогии с одномерным массивом, при явной инициализации массива входящего в состав многомерного массива его самая левая размерность может не указываться. Она определяется на основе инициализатора.
int MyArray[ ][3][3] = {
{{0,1}},
{{100},{200,210},{300}},
{{1000},{2000,2100}}
};
Транслятор понимает, что речь идёт об определении массива размерности 3*3*3.
А в таком случае
int MyArray[ ][3][3] = {
{{0,1}},
{{100},{200,210},{300}},
{{1000},{2000,2100}},
{{10000}}
};
предполагается размерность 4*3*3. В результате MyArray оказывается массивом из четырёх частично проинициализированных двумерных массивов. Следует помнить, что в C++ нет принципиальной разницы между массивом массивов произвольной размерности и обычным одномерным массивом. Потому и простор для творчества в деле инициализации многомерных массивов ограничивается левым индексом.
Билет №18
Работа со строками.
Строка в С++ - это массив символов, оканчивающийся нулевым символом ('\0'). Таким образом, можно определить строки двумя способами: как массив символов или как указатель на первый символ строки, например: char str1[10] = "string1"; // объявление строки с помощью массива символов
Итак, теперь подробнее. Вы уже знаете, что массив - это набор однородных значений. Так вот строка есть не что иное, как набор символов, и, соответственно, для хранения строк можно использовать символьные массивы. Например, строка "QWERTY" имет тип char[7], а пустая строка "" имеет тип char[1]. Почему char[1]? Именно потому, что любая строка завершается так называемым нулевым символом, то есть символом, код которого в ASCII-таблице равен 0 (этот символ также является escape-символом и его символьный эквивалент представляется как '\0'). Благодаря этому свойству Вы всегда можете определить конец строки, если у Вас строка занимает меньшее количество символов, чем то количество, которое было указано в квадратных скобках при оъявлении массива, т.е. определить фактическую длину строки, хранящейся в массиве. Одна из замечательных особенностей при работе со строками - это возможность упрощенной начальной инициализации. Например, Объявление char str[] = "ABCDE"; присваивает переменной-строке начальное значение "ABCDE". А точнее, создает массив из 6 символов: 'A','B','C','D','E' и символа '\0'.
Как видите начальная инициализация символьного массива действительно отличается от инициализации какого-либо другого массива - можно просто присвоить необходимую строку имени массива с пустыми квадратными скобками. С++ сам подсчитает длину строки и выделит соответствующий объем памяти под массив для размещения в нем требуемой строки. Сразу необходимо отметить, что С++ сам автоматически сделает последний элемент массива нулевым символом (а Вы уже помните, что любая строка обязательно заканчивается нулевым символом), то есть, хотя в данном случае Вы массиву str присваиваете строку "ABCDE", длина которой составляет 5 символов, C++ выделяет память под 6 символов, записывает туда строку и затем в последний (пятый при счете от 0) записывает нулевой символ. Следует также отметить, что при начальной инициализации символьного массива (как и любого другого) можно указывать в квадратных скобках его размер с целью дальнейшего использования массива еще для каких-либо целей (например, для хранения другой какой-либо строки): Объявление char str[10] = "ABCDE"; создает массив из 10 символов и первые пять элементов этого массива принимают значения 'A','B','C','D' и 'E' соответственно, остальные символы будут ноль-символы.
В данном случае в первые 5 элементов массива записывается строка "ABCDE", а всем остальным элементам присваиваются нули. Для начальной инициализации символьного массива можно использовать правила инициализации произвольного массива, то есть используя фигурные скобки, только в данном случае придется явно указывать нулевой символ, которым заканчивается строка. Давайте рассмотрим предшествующий пример с использованием общих правил начальной инициализации массива. char str[]={'A','B','C','D','E','\0'}; Как видите упрощеный вариант начальной инициализации строкового массива значительно проще и удобнее, но еще раз отметим, что его можно использовать только для символьных массивов. Типичная ошибка программирования. Не выделяется достаточно места в массиве символов для хранения нулевого символа, завершающего строку. Типичная ошибка программирования. Создание или использование "строки", которая не содержит завершающего нулевого символа. Типичная ошибка программирования. Путают символьные и строковые константы. Символьная константа - это один символ, заключенный в апострофы, например: 'A' или '\n'. Строковая константа - это последовательность символов, заключенная в двойные кавычки. В числе символов строки могут находится любые символьные константы, например, "Visual C++\n" состоит из следующих символов: 'V', 'i', 's', 'u', 'a', 'l', ' ', 'C', '+', '+', '\n', '\0'. Таким образом, "A" - это строковая константа и состоит из двух символов: 'A' и '\0'. Соседние строковые константы транслятором "склеиваются", например: "АБВ" "ГДЕ" означает то же, что "АБВГДЕ". Рассмотрим небольшой пример:
//Задана строка, скопировать ее в символьный массив. #include<iostream.h>
void main()
{
char str1 [ ] = "1234567890", /* объявляем символьный массив str1 и инициализируем его */
str2[11]; // объявляем символьный массив без инициализации
/* в цикле пока не встретится конец строки присваиваем текущему элементу массива str2 символ из массива str1 */
for(int i = 0; str1[i] != '\0'; i++) str2[i] = str1[i];
// копируем ноль-символ в str2.
str2 [i] = '\0';
cout << str2 << '\n'; // вывод строки на экран
}
Обратите внимание, выход из цикла происходит, когда str1[i] равно ноль-символу, т.е. ноль-символ не копируется в str2, следовательно это нужно сделать за циклом. Еще одна особенность работы с символьными массивами - если элементы произвольного массива можно вводить с клавиатура и выводить на экран только по одному элементу в цикле, то в символьный массив можно ввести сразу всю строку, используя оператор ввода cin >> Имя_массива; и, аналогичным образом, вывести сразу всю строку на экран, используя оператор вывода cout << Имя_массива; Следует сразу отметить, что при вводе с клавиатуры строки оператор cin автоматически добавляет в конец строки нулевой символ, так что Вы должны учитывать этот факт при указании количества элементов при объявлении массива. Например, #include <iostream.h>
void main()
{
char str[31]; // объявление символьного массива
cout<<"Enter a string (max 30 symbols):";
cin>>str; // ввод строки
cout<<"\nYou enter string:"<<str; // вывод строки
}
Как видите в данном примере выделяется память под 31 символ, но пользователю в приглашении указывается, что он может ввести строку с размером максимум 30 символов, учитывая тот факт, что оператор cin добавит еще один нулевой символ в конец строки автоматически, и под него также необходимо предусмотреть выделение памяти. Далее после приглашения вводим сразу всю строку с клавиатуры в массив и затем с соответствующим сообщением выводим всю строку на экран монитора. Билет №19
Модульная структура программы на C++.
В качестве модульной структуры программы принято использовать древовидную структуру, включая деревья со сросшимися ветвями. В узлах такого дерева размещаются программные модули, а направленные дуги (стрелки) показывают статическую подчиненность модулей, т.е. каждая дуга показывает, что в тексте модуля, из которого она исходит, имеется ссылка на модуль, в который она входит. Другими словами, каждый модуль может обращаться к подчиненным ему модулям, т.е. выражается через эти модули. При этом модульная структура программы, в конечном счете, должна включать и совокупность спецификаций модулей, образующих эту программу. Спецификация программного модуля содержит:
· синтаксическую спецификацию его входов, позволяющую построить на используемом языке программирования синтаксически правильное обращение к нему (к любому его входу);
· функциональную спецификацию модуля (описание семантики функций, выполняемых этим модулем по каждому из его входов).
В процессе разработки программы ее модульная структура может по-разному формироваться и использоваться для определения порядка программирования и отладки модулей, указанных в этой структуре. Поэтому можно говорить о разных методах разработки структуры программы
Метод восходящей разработки
Данный метод заключается в следующем. Сначала строится модульная структура программы в виде дерева. Затем поочередно программируются модули программы, начиная с модулей самого нижнего уровня (листья дерева модульной структуры программы), в таком порядке, чтобы для каждого программируемого модуля были уже запрограммированы все модули, к которым он может обращаться. После того, как все модули программы запрограммированы, производится их поочередное тестирование и отладка в принципе в таком же (восходящем) порядке, в каком велось их программирование. Такой порядок разработки программы на первый взгляд кажется вполне естественным: каждый модуль при программировании выражается через уже запрограммированные непосредственно подчиненные модули, а при тестировании использует уже отлаженные модули. Однако, современная технология не рекомендует такой порядок разработки программы. Во-первых, для программирования какого-либо модуля совсем не требуется наличия текстов используемых им модулей - для этого достаточно, чтобы каждый используемый модуль был лишь специфицирован (в объеме, позволяющем построить правильное обращение к нему), а для тестирования его возможно (и даже, как мы покажем ниже, полезно) используемые модули заменять их имитаторами (заглушками). Во-вторых, каждая программа в какой-то степени подчиняется некоторым внутренним для нее, но глобальным для ее модулей соображениям (принципам реализации, предположениям, структурам данных и т.п.), что определяет ее концептуальную целостность и формируется в процессе ее разработки. При восходящей разработке эта глобальная информация для модулей нижних уровней еще не ясна в полном объеме, поэтому очень часто приходится их перепрограммировать, когда при программировании других модулей производится существенное уточнение этой глобальной информации (например, изменяется глобальная структура данных). В-третьих, при восходящем тестировании для каждого модуля (кроме головного) приходится создавать ведущую программу (модуль), которая должна подготовить для тестируемого модуля необходимое состояние информационной среды и произвести требуемое обращение к нему. Это приводит к большому объему "отладочного" программирования и в то же время не дает никакой гарантии, что тестирование модулей производилось именно в тех условиях, в которых они будут выполняться в рабочей программе.
Метод нисходящей разработки
Метод нисходящей разработки заключается в следующем. Как и в предыдущем методе сначала строится модульная структура программы в виде дерева. Затем поочередно программируются модули программы, начиная с модуля самого верхнего уровня (головного), переходя к программированию какого-либо другого модуля только в том случае, если уже запрограммирован модуль, который к нему обращается. После того, как все модули программы запрограммированы, производится их поочередное тестирование и отладка в таком же (нисходящем) порядке. При этом первым тестируется головной модуль программы, который представляет всю тестируемую программу и поэтому тестируется при "естественном" состоянии информационной среды, при котором начинает выполняться эта программа. При этом те модули, к которым может обращаться головной, заменяются их имитаторами (так называемыми заглушками [5]). Каждый имитатор модуля представляется весьма простым программным фрагментом, который, в основном, сигнализирует о самом факте обращения к имитируемому модулю, производит необходимую для правильной работы программы обработку значений его входных параметров (иногда с их распечаткой) и выдает, если это необходимо, заранее запасенный подходящий результат. После завершения тестирования и отладки головного и любого последующего модуля производится переход к тестированию одного из модулей, которые в данный момент представлены имитаторами, если таковые имеются. Для этого имитатор выбранного для тестирования модуля заменяется самим этим модулем и, кроме того, добавляются имитаторы тех модулей, к которым может обращаться выбранный для тестирования модуль. При этом каждый такой модуль будет тестироваться при "естественных" состояниях информационной среды, возникающих к моменту обращения к этому модулю при выполнении тестируемой программы. Таким образом, большой объем "отладочного" программирования при восходящем тестировании заменяется программированием достаточно простых имитаторов используемых в программе модулей. Кроме того, имитаторы удобно использовать для того, чтобы подыгрывать процессу подбора тестов путем задания нужных результатов, выдаваемых имитаторами. При таком порядке разработки программы вся необходимая глобальная информация формируется своевременно, т.е. ликвидируется весьма неприятный источник просчетов при программировании модулей. Некоторым недостатком нисходящей разработки, приводящим к определенным затруднениям при ее применении, является необходимость абстрагироваться от базовых возможностей используемого языка программирования, выдумывая абстрактные операции, которые позже нужно будет реализовать с помощью выделенных в программе модулей. Однако способность к таким абстракциям представляется необходимым условием разработки больших программных средств, поэтому ее нужно развивать.
Автор
vlad-rudin
Документ
Категория
Без категории
Просмотров
129
Размер файла
72 Кб
Теги
informatika_shpor
1/--страниц
Пожаловаться на содержимое документа