Файл: Информация и формы ее представления Информационные процессы и технологии.docx

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 07.11.2023

Просмотров: 288

Скачиваний: 1

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

СОДЕРЖАНИЕ

Раздел 1 Основы информатики

1.3. ЭВМ как средство обработки информации

1.1 Информация и формы ее представления

Понятие количества информации

1.2 Информационные процессы и технологии

1.3 ЭВМ как средство обработки информации

Понятие архитектуры ЭВМ

Классификация ЭВМ

Структура и принципы функционирования ЭВМ

Основные характеристики вычислительной техники

Перспективы развития вычислительных средств

2.4 Операционная система MS-DOS

Системный блок

Монитор

Клавиатура

Мышь

Устройства ввода графических данных Для ввода графической информации используют сканеры, графические планшеты (дигитайзеры) и цифровые фотокамеры. Интересно отметить, что с помощью сканеров можно вводить и знаковую информацию. В этом случае исходный материал вводится в графическом виде, после чего обрабатывается специальными программными средствами (программами распознавания образов),Планшетные сканеры. Планшетные сканеры предназначены для ввода графической информации с прозрачного или непрозрачного листового материала (рис. 2.14). Принцип действия этих устройств состоит в том, что луч света, отраженный от поверхности материала (или прошедший сквозь прозрачный материал), фиксируется специальными элементами, называемыми приборами с зарядовой связью (ПЗС). Обычно элементы ПЗС конструктивно оформляют в виде линейки, располагаемой по ширине исходного материала. Перемещение линейки относительно листа бумаги выполняется механическим протягиванием линейки при неподвижной установке листа или протягиванием листа при неподвижной установке линейки. Рисунок 2.14 - Планшетный сканер ScanJet 3200C с аппаратным разрешением 600х1200 dpi фирмы Hewlett PackardОсновными потребительскими параметрами планшетных сканеров являются: разрешающая способность; производительность; динамический диапазон; максимальный размер сканируемого материала. Разрешающая способность планшетного сканера зависит от плотности размещения приборов ПЗС на линейке, а также от точности механического позиционирования линейки при сканировании. Типичный показатель для офисного применения: 600-1200 dpi (dpi – dots per inch – количество точек на дюйм). Для профессионального применения характерны показатели 1200-3000 dpi.Производительность сканера определяется продолжительностью сканирования листа бумаги стандартного формата и зависит как от совершенства механической части устройства, так и от типа интерфейса, использованного для сопряжения с компьютером.Динамический диапазон определяется логарифмом отношения яркости наиболее светлых участков изображения к яркости наиболее темных участков. Типовой показатель для сканеров офисного применения составляет 1,8-2,0, а для сканеров профессионального применения – от 2,5 (для непрозрачных материалов) до 3,5 (для прозрачных материалов).Ручные сканеры. Принцип действия ручных сканеров в основном соответствует планшетным. Разница заключается в том, что протягивание линейки ПЗС в данном случае выполняется вручную. Равномерность и точность сканирования при этом обеспечиваются неудовлетворительно, и разрешающая способность ручного сканера составляет 150-300 dpi.Барабанные сканеры. В сканерах этого типа исходный материал закрепляется на цилиндрической поверхности барабана, вращающегося с высокой скоростью. Устройства этого типа обеспечивают наивысшее разрешение (2400-5000 dpi) благодаря применению не ПЗС, а фотоэлектронных умножителей. Их используют для сканирования исходных изображений, имеющих высокое качество, но недостаточные линейные размеры (фотонегативов, слайдов и т. п.)Сканеры форм. Предназначены для ввода данных со стандартных форм, заполненных механически или <от руки». Необходимость в этом возникает при проведении переписей населения, обработке результатов выборов и анализе анкетных данных. От сканеров форм не требуется высокой точности сканирования, но быстродействие играет повышенную роль и является основным потребительским параметром.Штрих-сканеры. Эта разновидность ручных сканеров предназначена для ввода данных, закодированных в виде штрих-кода. Такие устройства имеют применение в розничной торговой сети.Графические планшеты (дигитайзеры). Эти устройства предназначены для ввода художественной графической информации. Существует несколько различных принципов действия графических планшетов, но в основе всех их лежит фиксация перемещения специального пера относительно планшета. Такие устройства удобны для художников и иллюстраторов, поскольку позволяют им создавать экранные изображения привычными приемами, наработанными для традиционных инструментов (карандаш, перо, кисть). К техническим характеристикам планшетам относятся: разрешающая способность (линий/мм), площадь рабочей области и количество уровней чувствительности к нажатию пера. На рис. 2.15 показан дигитайзер фирмы AIPTEK INK формата А6 с 512 уровнями чувствительности к нажатию пера. Рисунок 2.15 - Дигитайзер HYPER Pen 5000 фирмы AIPTEK INK Цифровые фото- и видеокамеры. Как и сканеры, эти устройства воспринимают графические данные с помощью приборов с зарядовой связью, объединенных в прямоугольную матрицу. Основным параметром цифровых фотоаппаратов является разрешающая способность, которая напрямую связана с количеством ячеек ПЗС в матрице. Наилучшие потребительские модели в настоящее время имеют до 1 млн. ячеек ПЗС и, соответственно, обеспечивают разрешение изображения до 800х1200 точек. У профессиональных моделей эти параметры выше. На рис. 2.16 показан недорогой фотоаппарат фирмы Mustek с оптическим разрешением 640х480 пикселей. Рисунок 2. 16 - Цифровая фотокамера VDC-200 фирмы MustekОсновные параметры видеокамер рассмотрим на примере камеры фирмы Mustek, представленной на рис. 2.17. Разрешение: 356х292 (HxV). Скорость передачи данных: 353х282, 16 бит цвета (сжатие), 20 кадров/с. Скорость передачи данных: 176x144, 16 бит цвета (сжатие), 30 кадров/с. Настройка фокусного расстояния: ручная. Экспозиция и баланс белого: автоматическая. Угол обзора ± 39°. Рисунок 2.17 - Цифровая видеокамера фирмы Mustek Устройства вывода данных В качестве устройств вывода данных, дополнительных к монитору, используют печатающие устройства (принтеры), позволяющие получать копии документов на бумаге или прозрачном носителе. По принципу действия различают матричные, лазерные, светодиодные и струйные принтеры.Матричные принтеры. Это простейшие печатающие устройства (см. рис. 2.18). Данные выводятся на бумагу в виде оттиска, образующегося при ударе цилиндрических стержней («иголок») через красящую ленту. Качество печати матричных принтеров напрямую зависит от количества иголок в печатающей головке. Наибольшее распространение имеют 9-игольчатые и 24-игольчатые матричные принтеры. Последние позволяют получать оттиски документов, не уступающие по качеству документам, исполненным на пишущей машинке. Рисунок 2.18 - Матричный 9-игольчатый принтер формата A3 Epson FX-1180 производительностью 396 cpsПроизводительность работы матричных принтеров оценивают по количеству печатаемых знаков в секунду (cps – characters per second). Обычными режимами работы матричных принтеров являются: draft – режим черновой печати, normal – режим обычной печати и режим NLQ (Near Letter Quality), который обеспечивает качество печати, близкое к качеству пишущей машинки.Лазерные принтеры. Лазерные принтеры обеспечивают высокое качество печати, не уступающее, а во многих случаях и превосходящее полиграфическое. Они отличаются также высокой скоростью печати, которая измеряется в страницах в минуту (ррт – page per minute). Как и в матричных принтерах, итоговое изображение формируется из отдельных точек. Рисунок 2.19 - Лазерный принтер HP LaserJet 4000 производительностью 16 ppmПринцип действия лазерных принтеров следующий: в соответствии с поступающими данными лазерная головка испускает световые импульсы, которые отражаются от зеркала и попадают на поверхность светочувствительного барабана; горизонтальная развертка изображения выполняется вращением зеркала; участки поверхности светочувствительного барабана, получившие световой импульс, приобретают статический заряд; барабан при вращении проходит через контейнер, наполненный красящим составом (тонером), и тонер закрепляется на участках, имеющих статический заряд; при дальнейшем вращении барабана происходит контакт его поверхности с бумажным листом, в результате чего происходит перенос тонера на бумагу; лист бумаги с нанесенным на него тонером протягивается через нагревательный элемент, в результате чего частицы тонера спекаются и закрепляются на бумаге. К основным параметрам лазерных принтеров относятся: разрешающая способность, dpi (dots per inch – точек на дюйм); производительность (страниц в минуту); формат используемой бумаги; объем собственной оперативной памяти. При выборе лазерного принтера необходимо также учитывать параметр стоимости оттиска, то есть стоимость расходных материалов для получения одного печатного листа стандартного формата А4. К расходным материалам относится тонер и барабан, который после печати определенного количества оттисков утрачивает свои свойства. В качестве единицы измерения используют цент на страницу (имеются в виду центы США). В настоящее время теоретический предел по этому показателю составляет порядка 1,0-1,5. На практике лазерные принтеры массового применения обеспечивают значения от 2,0 до 6,0.Основное преимущество лазерных принтеров заключается в возможности получения высококачественных отпечатков. Модели среднего класса обеспечивают разрешение печати до 600 dpi, а профессиональные модели – до 1200 dpi.Светодиодные принтеры. Принцип действия светодиодных принтеров похож на принцип действия лазерных принтеров. Разница заключается в том, что источником света является не лазерная головка, а линейка светодиодов. Поскольку эта линейка расположена по всей ширине печатаемой страницы, отпадает необходимость в механизме формирования горизонтальной развертки и вся конструкция получается проще, надежнее и дешевле. Типичная величина разрешения печати,. для светодиодных принтеров составляет порядка 600 dpi.Струйные принтеры. В струйных печатающих устройствах изображение на бумаге формируется из пятен, образующихся при попадании капель красителя на бумагу (рис. 2.20). Выброс микрокапель красителя происходит под давлением, которое развивается в печатающей головке за счет парообразования. В некоторых моделях капля выбрасывается щелчком в результате пьезоэлектрического эффекта – этот метод позволяет обеспечить более стабильную форму капли, близкую к сферической.Качество печати изображения во многом зависит от формы капли и ее размера, а также от характера впитывания жидкого красителя поверхностью бумаги. В этих условиях особую роль играют вязкостные свойства красителя и свойства бумаги. Рисунок 2.20 - Струйный принтер Stylus Color 640 с разрешением 1440 dpi и скоростью печати: 5 страниц в минуту в монохроме, 3,5 страницы в минуту в цвете К положительным свойствам струйных печатающих устройств следует отнести относительно небольшое количество движущихся механических частей и, соответственно, простоту и надежность механической части устройства и его относительно низкую стоимость. Основным недостатком, по сравнению с лазерными принтерами, является нестабильность получаемого разрешения, что ограничивает возможность их применения в черно-белой полутоновой печати.В то же время, сегодня струйные принтеры нашли очень широкое применение в цветной печати. Благодаря простоте конструкции они намного превосходят цветные лазерные принтеры по показателю качество/цена. При разрешении выше 600 dpi они позволяют получать цветные оттиски, превосходящие по качеству цветные отпечатки, получаемые фотохимическими методами.При выборе струйного принтера следует обязательно иметь виду параметр стоимости печати одного оттиска. При том, что цена струйных печатающих устройств заметно ниже, чем лазерных, стоимость печати одного оттиска на них может быть в несколько раз выше.Устройства хранения данных Необходимость во внешних устройствах хранения данных возникает в двух случаях: когда на вычислительной системе обрабатывается больше данных, чем можно разместить на базовом жестком диске; когда данные имеют повышенную ценность и необходимо выполнять регулярное резервное копирование на внешнее устройство (копирование данных на жестком диске не является резервным и только создает иллюзию безопасности). В настоящее время для внешнего хранения данных используют несколько типов устройств, использующих магнитные или магнитооптические носители.Стримеры. Стримеры – это накопители на магнитной ленте. Их отличает сравнительно низкая цена. К недостаткам стримеров относят малую производительность (она связана прежде всего с тем, что магнитная лента – это устройство последовательного доступа) и недостаточную надежность (кроме электромагнитных наводок, ленты стримеров испытывают повышенные механические нагрузки и могут физически выходить из строя).Емкость магнитных кассет (картриджей) для стримеров составляет до нескольких сот Мбайт. Дальнейшее повышение емкости за счет повышения плотности записи снижает надежность хранения, а повышение емкости за счет увеличения длины ленты сдерживается низким временем доступа к данным.ZIP-накопители.ZIP-накопители выпускаются компанией Iomega, специализирующейся на создании внешних устройств для хранения данных. Устройство работает с дисковыми носителями, по размеру незначительно превышающими стандартные гибкие диски и имеющими емкость 100/250 Мбайт. ZIP-накопители выпускаются во внутреннем и внешнем исполнении. В первом случае их подключают к контроллеру жестких дисков материнской платы, а во втором – к стандартному параллельному порту, что негативно сказывается на скорости обмена данными.Накопители HiFD. Основным недостатком ZIP-накопителей является отсутствие их совместимости со стандартными гибкими дисками 3,5 дюйма. Такой совместимостью обладают устройства HiFD компании Sony. Они позволяют использовать как специальные носители емкостью 200 Мбайт, так и обычные гибкие диски. В настоящее время распространение этих устройств сдерживается повышенной ценой.Накопители JAZ. Этот тип накопителей, как и ZIP-накопители, выпускается компанией Iomega. По своим характеристикам JAZ-носитель приближается к жестким дискам, но в отличие от них является сменным. В зависимости от модели накопителя на одном диске можно разместить 1 или 2 Гбайт данных.Магнитооптические устройства. Эти устройства получили широкое распространение в компьютерных системах высокого уровня благодаря своей универсальности. С их помощью решаются задачи резервного копирования, обмена данными и их накопления. Однако достаточно высокая стоимость приводов и носителей не позволяет отнести их к устройствам массового спроса.В этом секторе параллельно развиваются 5,25- и 3,5-дюймовые накопители, носители для которых отличаются в основном форм-фактором и емкостью. Последнее поколение носителей формата 5,25" достигает емкости 5,2 Гбайт. Стандартная емкость для носителей 3,5" – 640 Мбайт.В формате 3,5" недавно была разработана новая технология GIGAMO, обеспечивающая емкость носителей в 1,3 Гбайт, полностью совместимая сверху вниз с предыдущими стандартами. В перспективе ожидается появление накопителей и дисков форм-фактора 5,25", поддерживающих технологию NFR (Near Field Recording), которая обеспечит емкость дисков до 20 Гбайт, а позднее и до 40 Гбайт.Устройства обмена данными Модем. Устройство, предназначенное для обмена информацией между удаленными компьютерами по каналам связи, принято называть модемом (МОдулятор + ДЕМодулятор) (см. рис. 2.21). При этом под каналом связи понимают физические линии (проводные, оптоволоконные, кабельные, радиочастотные), способ их использования (коммутируемые и выделенные) и способ передачи данных (цифровые или аналоговые сигналы). В зависимости от типа канала связи устройства приема-передачи подразделяют на радиомодемы, кабельные модемы и прочие. Наиболее широкое применение нашли модемы, ориентированные на подключение к коммутируемым телефонным каналам связи.Цифровые данные, поступающие в модем из компьютера, преобразуются в нем путем модуляции (по амплитуде, частоте, фазе) в соответствии с избранным стандартом (протоколом) и направляются в телефонную линию. Модем-приемник, понимающий данный протокол, осуществляет обратное преобразование (демодуляцию) и пересылает восстановленные цифровые данные в свой компьютер. Таким образом обеспечивается удаленная связь между компьютерами и обмен данными между ними.К основным потребительским параметрам модемов относятся: производительность (бит/с); поддерживаемые протоколы связи и коррекции ошибок; шинный интерфейс, если модем внутренний (ISA или РСI). От производительности модема зависит объем данных, передаваемых в единицу времени. От поддерживаемых протоколов зависит эффективность взаимодействия данного модема с сопредельными модемами (вероятность того, что они вступят во взаимодействие друг с другом при оптимальных настройках). От шинного интерфейса в настоящее время пока зависит только простота установки и настройки модема (в дальнейшем при общем совершенствовании каналов связи шинный интерфейс начнет оказывать влияние и на производительность).По способу подключения модемы делятся на два вида: внешние и внутренние. Внешний модем подключается к одному из COM-портов. Внутренний вставляется внутрь системного блока в виде платы расширения. На рис. 2.23 представлены внешний и внутренний факс/модемы Courier V.34 фирмы US Robotics. Рисунок 2.21 - Внешний и внутренний факс/модемы Courier V.34 фирмы US Robotics2.3 Виды программного обеспечения ЭВМНазначением ЭВМ является выполнение программ. Программа содержит команды, определяющие порядок действий компьютера. Совокупность программ для компьютера образует программное обеспечение (ПО). По функциональному признаку различают следующие виды ПО: системное; прикладное; инструментальное. Рисунок 2.22 - Структура программного обеспеченияПод системным (базовым) понимается программное обеспечение, включающее в себя операционные системы, сетевое ПО, сервисные программы, а также средства разработки программ (трансляторы, редакторы связей, отладчики и пр.).Основные функции операционных систем (ОС) заключаются в управлении ресурсами (физическими и логическими) и процессами вычислительных систем. Физическими ресурсами являются: оперативная память, процессор, монитор, печатающее устройство, магнитные и оптические диски. К логическим ресурсам можно отнести программы, файлы, события и т. д. Под процессом понимается некоторая последовательность действий, предписанная соответствующей программой и используемыми ею данными.В настоящее время существует большое количество ОС, разработанных для ЭВМ различных типов. На ЭВМ Единой Системы (ЕС ЭВМ), например, использовались такие операционные системы, как СВМ и ОС ЕС, на малых ЭВМ (СМ-4, СМ-1420 и др.) - ОС РВ и RSX-11. На персональных ЭВМ долгое время эксплуатировалась ОС-MS-DOS. В настоящее время получили распространение системы Windows , Unix, Linix.Сетевое ПО предназначено для управления общими ресурсами в распределенных вычислительных системах: сетевыми накопителями на магнитных дисках, принтерами, сканерами, передаваемыми сообщениями и т. д. К сетевому ПО относят ОС, поддерживающие работу ЭВМ в сетевых конфигурациях (так называемые сетевые ОС), а также отдельные сетевые программы (пакеты), используемые совместно с обычными, не сетевыми ОС.Например, большое распространение получили следующие сетевые ОС: NetWare 4.1 (фирма Novell), Windows NT Server 3.5 (фирма Microsoft) и LAN Server 4.0 Advanced (фирма IBM). Однако в последнее время лидирующие позиции начинает занимать ОС Windows 2000 Server фирмы Microsoft.  Для расширения возможностей операционных систем и предоставления набора дополнительных услуг используются сервисные программы. Их можно разделить на следующие группы: интерфейсные системы; оболочки операционных систем; утилиты. Интерфейсные системы являются естественным продолжением операционной системы и модифицируют как пользовательский, так и программный интерфейсы, а также реализуют дополнительные возможности по управлению ресурсами ЭВМ. В связи с тем, что развитая интерфейсная система может изменить весь пользовательский интерфейс, часто их также называют операционными системами. Это относится, например, к Windows.Оболочки операционных систем, в отличие от интерфейсных систем, модифицируют только пользовательский интерфейс, предоставляя пользователю качественно новый интерфейс по сравнению с реализуемым операционной системой. Такие системы существенно упрощают выполнение часто запрашиваемых функций, например, таких операций с файлами, как копирование, переименование и уничтожение, а также предлагают пользователю ряд дополнительных услуг. В целом, программы-оболочки заметно повышают уровень пользовательского интерфейса, наиболее полно удовлетворяя потребностям пользователя.На ПЭВМ широко используются такие программы-оболочки, как Norton Commander, FAR Manager и Windows Commander.Утилиты предоставляют пользователям средства обслуживания компьютера и его ПО. Они обеспечивают реализацию следующих действий: обслуживание магнитных дисков; обслуживание файлов и каталогов; предоставление информации о ресурсах компьютера; шифрование информации; защита от компьютерных вирусов; архивация файлов и др. Существуют отдельные утилиты, используемые для решения одного из перечисленных действий, и многофункциональные комплекты утилит. В настоящее время для ПЭВМ среди многофункциональных утилит одним из наиболее совершенных является комплект утилит Norton Utilities. Существуют его версии для использования в среде DOS и Windows.Средства разработки программ используются для разработки нового программного обеспечения как системного, так и прикладного.Прикладным называется ПО, предназначенное для решения определенной целевой задачи из проблемной области. Часто такие программы называют приложениями.Спектр проблемных областей в настоящее время весьма широк и включает в себя по крайней мере следующие: промышленное производство, инженерную практику, научные исследования, медицину, управление (менеджмент), делопроизводство, издательскую деятельность, образование и т. д. Из всего разнообразия прикладного ПО выделяют группу наиболее распространенных программ (типовые пакеты и программы), которые можно использовать во многих областях человеческой деятельности.К типовому прикладному ПО относят следующие программы: текстовые процессоры; табличные процессоры; системы иллюстративной и деловой графики (графические процессоры); системы управления базами данных; экспертные системы; программы математических расчетов, моделирования и анализа экспериментальных данных. Предлагаемые на рынке ПО приложения, в общем случае, могут быть выполнены как отдельные программы либо как интегрированные системы. Интегрированными системами обычно являются экспертные системы, программы математических расчетов, моделирования и анализа экспериментальных данных, а также офисные системы. Примером мощной и широко распространенной интегрированной системы является офисная система Microsoft Office.Поскольку разработка ПО любого назначения, как правило, является довольно сложным и трудоемким процессом, дальнейший материал настоящего раздела посвятим общим вопросам разработки программ и инструментальному ПО.Инструментальное ПО Инструментальное программное обеспечение представляет комплексы программ для создания других программ. Программы инструментального программного обеспечения управляются системными программами, поэтому они относятся к более высокому уровню. К инструментальному ПО относятся: компиляторы, редакторы связей, отладчики, интегрированные системы разработки ПО, например, интегрированная система Delphi, Visual Studio и т.п..2.4 Операционная система MS-DOS Операционная система MS-DOS – это однопользовательская, однозадачная, не сетевая 16-разрядная операционная система (ОС), ориентированная на использование на ПЭВМ с микропроцессором Intel 8088(80286).Краткая история появления данной операционной системы такова. В октябре 1980 г. менеджеры фирмы IBM занялись поисками ОС для своего 16-разрядного персонального компьютера (ПК), находящегося в стадии разработки. В тот период на ПЭВМ наиболее широко применялась ОС CP/M (Control Program for MicroComputers) фирмы Digital Research. Не достигнув приемлемых соглашений с Digital Research, фирма IBM обратилась к фирме Microsoft (президент – Билл Гейтс). В тот момент у Microsoft не было соответствующей OС, но ей была известна небольшая фирма Seattle Computer Products, которая имела такую OС. За 50 000$ Билл Гейтс приобрел права на эту OС. В дальнейшем эта OС послужила основой для MS-DOS. В ноябре 1980 г. Microsoft и IBM подписали договор на разработку OС для IBM PC. В феврале 1981 г. появилась первая версия PC/MS-DOS, которая работала на IBM PC, в августе того же года – PC DOS 1.0 (эта версия была утверждена для применения на IBM PC).Операционная система MS-DOS позволяет полностью использовать возможности процессоров Intel 8088 и Intel 80286, работающих в реальном режиме. Основными характеристиками данной ОС являются: максимальный объем адресуемой физической памяти – 640 Кбайт; максимальный объем памяти, доступный из прикладных программ 640 Кбайт. Последние версии MS-DOS (начиная с 5.0) могут использовать адресное пространство между 640 Кбайт и 1 Мбайт для размещения своих составных частей и некоторых драйверов, освобождая тем самым память в адресном пространстве 0-640 Кбайт для использования прикладными программами; представление всех ресурсов персонального компьютера для одной, активной в настоящий момент, программы; развитая файловая система и процессор командного языка; слабая поддержка интерактивных средств взаимодействия с пользователем; занимаемый объем на диске, в зависимости от версии, от 1 Мбайта до 6 Мбайт. (минимум, при котором можно работать – 100 Кбайт). Основные составные части MS-DOS MS-DOS состоит из следующих компонент: блок начальной загрузки (размещается в 1-м секторе 0-дорожки 0-стороны системной дискеты); модуль расширения BIOS (IO.SYS для версии 5.0 и выше); модуль обработки прерываний (MSDOS.SYS для версии 5.0 и выше), командный процессор (COMMAND.COM); внешние команды (программы) MS-DOS; драйверы устройств; файл Config.SYS; файл Autoexec.bat. Ядро MS-DOS включает блок начальной загрузки и файлы IO.SYS, MSDOS.SYS.Блок начальной загрузки размещается  в 1-м секторе 0-дорожки 0-стороны системной дискеты и/или в 1-м секторе HDD-диска, в разделе, отведенном под DOS. Выполняет следующие функции: просматривает корневой каталог системного диска и проверяет, являются ли первые два файла в каталоге – файлами IO.SYS и MSDOS.SYS. Если ДА – загружает их в ОЗУ и передает управление MS-DOS, если НЕТ – выдает сообщение на экране и ожидает нажатия какой-либо клавиши пользователем: Non-System disk or disk errorReplace and press any key when ready (Не системный диск или ошибка дискаЗамените и нажмите какую-либо клавишу, когда будет готово)Именно поэтому , при создании системной дискеты необходимо переносить на неё файлы IO.SYS и MSDOS.SYS с помощью специальной программы SYS.COM.Модуль расширения BIOS IO.SYSЭто резидентный модуль (всегда находится в ОЗУ после загрузки, пока включен ПК). Взаимодействует с BIOS. Расширяет возможности BIOS или изменяет ее свойства (там, где необходимо) с помощью дополнительных драйверов.Модуль обработки прерываний MSDOS.SYSЭто резидентный модуль. Обеспечивает интерфейс высокого уровня для прикладных программ, содержит программные средства для управления файлами, устройствами ввода-вывода, обработки исключительных ситуаций (ошибок) и др. Прикладная программа вызывает функции этого модуля через механизм программных прерываний, передавая (принимая) информацию к (от) MS-DOS через регистры CPU или (и) области памяти ОЗУ. MSDOS.SYS транслирует (переводит) запрос прикладной программы в один или несколько вызовов IO.SYS + BIOS.Командный процессор COMMAND.COMОтдельный модуль MS-DOS. Этот модуль может быть заменен на другой, более удобный. Предназначен для приема команд с клавиатуры или из *.bat - файлов и их выполнения; выполнения команд файла Autoexec.bat при загрузке MS-DOS; загрузки в ОЗУ и запуск на выполнение прикладных программ в среде MS-DOS.Командный процессор состоит из 3-х частей : резидентной (размещается в ОЗУ сразу после MSDOS.SYS, включает процедуры обслуживания некоторых прерываний, процедуры обработки стандартных ошибок MS-DOS, процедуру загрузки транзитной части командного процессора); инициализирующей (в ОЗУ следует сразу за резидентной частью; во время загрузки OС ей передается управление; она выполняет файл Autoexec.bat и некоторые другие действия; эта часть командного процессора стирается из ОЗУ первой же загруженной программой); транзитной (загружается в старшие адреса ОЗУ; обрабатывает все внутренние команды, команды с клавиатуры и из *.bat-файлов; выдает системную подсказку MS-DOS; загружает в ОЗУ программы и передает им управление). Внешние команды (программы)Дополнительные программы, входящие в MS-DOS, выполняющие определенные функции.Драйверы устройствСпециальные резидентные программы, которые управляют внешними устройствами. Драйверы загружаются в ОЗУ в том порядке, как они указаны в файле CONFIG.SYS.Файл CONFIG.SYSСпециальный текстовый файл, где содержится информация о подгружаемых дополнительных драйверах и некоторая другая информация, касающаяся непосредственно MS-DOS и выполняемых в ее среде прикладных программ. MS-DOS выполняет этот файл автоматически, сразу после загрузки COMMAND.COM.Файл AUTOEXEC.BATСпециальный текстовый файл, в котором содержится дополнительная настроечная информация. MS-DOS выполняет этот файл автоматически, сразу после выполнения файла CONFIG.SYSНачальная загрузка MS-DOS 1. При включении ПК вначале выполняются программы BIOS.2. После тестирования оборудования и выполнения других действий процедура POST (из модуля BIOS) осуществляет поиск и загрузку блока начальной загрузки по следующему алгоритму: вначале производится поиск на устройстве A:. Если блок не найден, то поиск выполняется на устройстве C:. Если снова поиск не завершился успешно, то вызывается встроенный в ПЗУ BASIC или производятся  другие действия, записанные в ПЗУ.3. Блок начальной загрузки производит поиск в корневом каталоге  системной дискеты (диска) файлов IO.SYS и MSDOS.SYS (эти файлы должны быть первыми и именно в таком порядке).4. Блок начальной загрузки производит загрузку файла IO.SYS и передает ему управление.5. Файл IO.SYS выполняет следующие действия: загружает и настраивает MSDOS.SYS; определяет состояние подключенных устройств; инициализирует подключенные устройства; загружает необходимые драйверы устройств; передает управление файлу MSDOS.SYS. 6. Файл MSDOS.SYS выполняет следующие действия: инициализирует (настраивает) свои внутренние рабочие таблицы; загружает драйверы, указанные в файле CONFIG.SYS; загружает командный процессор (файл COMMAND.COM). 7. Командный процессор выполняет команды, указанные в файле Autoexec.bat.8. Командный процессор выдает на экран монитора системную подсказку  MS-DOS и ожидает ввода команд пользователя.Файловая система MS-DOS Файл  (по-английски file – папка, скоросшиватель) – это поименованная область памяти на каком-либо физическом носителе, предназначенная для хранения информации.Совокупность средств MS-DOS, обеспечивающих доступ к информации на внешних носителях, называется системой управления файлами, или файловой системой.Одно из понятий файловой системы MS-DOS – логический диск. В некотором приближении можно считать, что с точки зрения MS-DOS каждый логический диск – это отдельный магнитный диск. Каждый логический диск имеет своеуникальное имя.В качестве имени логического диска используются буквы английского алфавита от A до Z (включительно). Таким образом, количество логических дисков, может быть не более 26.Буквы A и B – отведены строго под имеющиеся в IBM PC дисководы.Начиная с буквы C именуются логические диски (разделы) жесткого диска (рис. 2.23).В случае, если данный IBM PC имеет только один FDD, буква B пропускается (см. рис. 2.24).Как правило, только логические диски A и C могут быть системными.

Файловая структура логического диска

Раздел 3 Основные принципы программирования

3.1. Этапы подготовки и решения задач на ЭВМ

3.2. Алгоритмы и способы их описания

3.3. Компиляция и интерпретация программ

3.4. Стили программирования

3.1 Этапы подготовки и решения задач на ЭВМ

3.2 Алгоритмы и способы их описания

3.3. Компиляция и интерпретация программ

3.4. Стили программирования

Раздал 6 Структуры данных

Раздел 7 Файлы данных

Раздел 8 Подпрограммы

Раздел 9 Объектно-ориентированное программирование

9.1. Описание класса

9.2. Описание объектов

9.4. Наследование

9.5. Иерархия классов

9.6. Виртуальные методы. Полиморфизм.

9.7. Контейнерные классы

Методы класса При вызове методов необходимо связать метод с объектом этого класса [2]. Поэтому имена объектов ( p ) связаны с именем функции (метода) операцией точка (.):p.InitPoint(10,10);p.relmove(5,10); Замечание: Это напоминает доступ к полям структуры.Вызов методов InitPoint() и relmove() приводило к изменению значений полей x и y. В следующем примере задание значений полей в методе Vvod() будет осуществляться с клавиатуры: class TPoint { private: int x,y;public: void InitPoint ( int newx, int newy) { x = newx;y = newy ;} void Vvod(){std::cout<<"Vvedi X Y:";std::cin>> x >> y;}. . . };Вставим вызов этого метода в главную программу: int main(){ TPoint p;// описание объектаp.Vvod();std::cout<<"x="<< p.getx()<<",\ty="<< p.gety()<<"\n"; return 0;} Результаты работы программы приведены на рисунке 9.2. Рисунок 9.2 – Результат использования метода Vvod()Конструкторы'>КонструкторыB отличии от предыдущего примера удобнее инициализировать поля объекта автоматически в момент его создания, а не явно, вызовом соответствующего метода. Такой способ реализуется с помощью особого метода класса, называемого конструктором.Конструктор - это метод, выполняющийся автоматически в момент создания объекта.Конструктор отличается от других методов: Имя конструктора совпадает с именем класса; У конструктора не существует возвращаемого значения. Заменим метод InitPoint() на конструктор:class TPoint { private: int x,y;public:TPoint(int newx, int newy) // конструктор {x=newx;y=newy; } void relmove ( int dx, int dy ) {x+= dx; y += dy ; } int getx ( void ) { return x ; }int gety ( void ) { return y ; } };int main(int argc, char *argv[]){ TPoint p(10,10); //инициализация объекта р std::cout<<"x="<< p.getx()<<",\ty="<< p.gety()<<"\n"; . . .}В качестве второго примера создадим класс Counter, объекты которого могут хранить количественную меру какой-либо изменяющейся величины. При наступлении некоторого события счетчик увеличивается на единицу. Обращение к счетчику происходит, как правило, для того, чтобы узнать текущее значение той величины, для изменения которой он предназначен.#include "stdafx.h"#include "iostream"class Counter{ private: int count;public: Counter ( ):count(0){ } //конструктор void inc_count ( )//метод увеличения счетчика на 1{count++; }int get_count( )//метод возвращает значение счетчика{ return count; }};int _tmain(int argc, _TCHAR* argv[]){ Counter c1, c2;//создание объектов c1 и c2std::cout<std::cout<c1.inc_count(); c1.inc_count(); //увеличение с1 на 2c2.inc_count(); //увеличение с2 на 1std::cout<std::cout<return 0;}Результаты программы приведены на рисунке 9.3. Рисунок 9.3. – Результаты работы программыОдной из наиболее часто возлагаемых на конструктор задач является инициализация полей объекта. Инициализация полей обычно реализуется с помощью списка инициализации, который располагается между заголовком и телом функции-конструктора. После заголовка ставится двоеточие. Инициализирующие значения помещены в круглые скобки после имени поля.Counter ( ):count(0) {/* тело функции*/ } Если инициализируются несколько полей, то значения разделяются запятыми.ДеструкторыКроме специального метода конструктор, который вызывается при создании объекта, существует другой особый метод, автоматически вызываемый при уничтожении объекта, называемый деструктором [2].Деструктор имеет имя, совпадающее с именем конструктора, перед которым стоит тильда .class Prim{ private: int dat;public:Prim(): dat(0){ }Prim(){ }}; Наиболее распространённое применение деструкторов – освобождение памяти, выделенной конструктором при создании объекта.Определение методов может быть реализовано как внутри самого класса, так и вне класса. Во втором случае внутри класса содержится лишь прототип функции, а сама функция определяется позже. Тогда перед именем функции указывается имя класса и символ ::Вернемся к примеру класса TPoint. Рассмотрим в этом примере реализацию метода relmove()вне класса и добавим деструктор для класса TPoint.class TPoint { private: int x,y;public:TPoint(int newx, int newy) {x=newx;y=newy; } void relmove ( int dx, int dy ); int getx ( void ){ return x ; } int gety ( void ) { return y ; } Tpoint( ){ }};void TPoint::relmove(int dx, int dy){x+= dx; y += dy ; } ЗАМЕЧАНИЯ:1)Класс может иметь несколько конструкторов с разными параметрами для разных видов инициализации.2)Конструктор, вызываемый без параметров, называется конструктором по умолчанию.3)Деструктор вызывается автоматически, когда объект выходит из области видимости:• для локальных объектов — при выходе из блока, в котором они объявлены;• для глобальных — как часть процедуры выхода из main( );• для объектов, заданных через указатели деструктор вызывается неявно при использовании операции delete. Деструктор:• не имеет аргументов и возвращаемого значения;• не может быть объявлен, как const или static;• не наследуется;• может быть виртуальным.Вернемся ко второму примеру, где был создан класс Counter. При решении разных задач может возникнуть необходимость инициализации счетчика разными значениями, а не только нулем. Для этого создадим еще один конструктор:class Counter{ private: int count;public:Counter ( ):count(0)//конструктор, инициализирующий нулем { }Counter (int c): count(c)//конструктор задает любое нач. значение{ } void inc_count ( ) {count++; } int get_count( ){ return count; }

Наследование



char Symb=fgetc(fin);

Если при обработке достигается конец файла, то функция fgetc() возвращает значение EOF(end of file).

Функция fputc() заносит значение символа Symb в файл, на который указывает указатель out. Формат вызова функции:

f putc(Symb,out);

Пример 1. Текст из файла my_char.txtвыводится на экран. Если файл не найден, на экран выводится сообщение "File not found!":

#include "stdafx.h"

int main()

{

FILE *ptr; //описание указателя на файл

char ch;

if ((ptr=fopen("my_char.txt","r"))!=NULL)/*открытие файла для чтения*/

{

ch=fgetc(ptr); //чтение первого символа из файла

while (!feof(ptr)) //цикл пока не достигнут конец файла

{

printf("%c",ch); //вывод символа, взятого из файла

ch=fgetc(ptr); //чтение следующего символа из файла

}

fclose(ptr); //закрытие файла

}

else printf("\nFile not found!");

return 0;

}
В этом примере для чтения файла используется указатель ptr. При открытии файла производится проверка. Если переменной ptr присвоено значение NULL, то файл не найден; на экран выводится соответствующее сообщение, и программа завершается. Если ptr получил ненулевое значение, то файл открыт. Далее выполняется чтение символов из файла до тех пор, пока не будет достигнут конец файла (!feof(ptr)). Прочитанный символ помещается в переменную ch, а затем выводится на экран.

Пример 2. Записать в файл буквы, вводимые с клавиатуры. Ввод продолжается до нажатия клавиши F6 или CTRL/z (ввод символа EOF – конца файла):

#include "stdafx.h"

int main(void)

{

char c;

FILE *out; // описание указателя на файл

out=fopen("Liter.txt","w"); //открытие файла для записи

while ( (c=getchar( ))!=EOF) /*пока не будет введен символ конца */

fputc(c,out); // запись введенного символа в файл

fclose(out); //закрытие файла

return 0;

}

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

Рассмотрим пример:


fgets(string, n, fp);

Функция возвращает указатель на строку string при успешном завершении и константу NULL в случае ошибки либо достижения конца файла.

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

Например:

fputs("Ехаmple", fp);

При возникновении ошибки возвращается значение EOF.

Пример 3. Имеется текстовый файл. Определить длины строк этого файла:

#include

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

{

setlocale(0,"RUS");

char st[125];

int a=0;

FILE *fo;

fo = fopen("prim.txt","r"); //открытие файла для чтения

while (!feof(fo))//цикл пока не конец файла

{

fgets(st,125,fo); //читать строку символов

if (!feof(fo)) //если не конец файла

{

a=strlen(st); //определить длину строки

printf("Длина:%d строка:%s \n",a,st);

}

}

fclose(fo);

return 0;

}

Функции fscanf() и fprintf() выполняют форматированный ввод/вывод.
Чтение из файла выполняет функция fscanf():

fscanf(fin,["строка формата"],[список адресов переменных]);

Функция возвращает количество введенных из файла значений или EOF.

Запись в файл осуществляет функция fprintf():

fprintf(out,["строка формата"],[список переменных, констант]);

Возвращает количество выведенных в файл байт (символов) или EOF.

Строка формата функций fscanf() и fprintf() формируется так же, как было описано ранее в главе, посвященной консольному вводу/выводу и функциям printf() и scanf().

Следует заметить, что вызов функции

fscanf(stdin,[строка формата],[список адресов переменных]);

эквивалентен вызову

scanf([строка формата],[список адресов переменных]);

Аналогично,

fprintf(stdout, [строка формата],[список переменных, констант]);

эквивалентно

printf([строка формата],[список переменных, констант]);

Рассмотрим примеры программ, использующих эти функции.

Пример 4. В программе создается массив, состоящий из четырех целых чисел. Вывести массив в файл:

#include "stdafx.h"

#define n 4

int main()

{

int i=0;

int array[n]={4,44,446,4466}; /*описание и инициализация масcива */

FILE *out; //описание указателя на файл

out=fopen("num_arr.txt","w"); //открытие файла для записи

for(;i
fprintf(out, "%6d",array[i]); //запись в файл элемента массива

fclose(out); //закрытие файла

return 0;

}

В результате выполнения программы в файл num_arr.txt будет помещена следующая информация:

 

 

 

 

0

4

 

 

 

 

4

4

 

 

 

4

4

6

 

 

4

4

6

6

















































































































































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

#include "stdafx.h"

int main()

{

int S=0, count=0, numb; //описание переменных

FILE *in; //описание укателя на файл

if((in=fopen("num_arr.txt","r"))!=NULL)/*открытие файла для чтения*/

{

while (!feof(in)) //цикл пока не конец файла

{

fscanf(in,"%d",&numb); //читать из файла число в переменную numb

S+=numb; // добавить numb в сумму

count++; //увеличиваем счетчик на 1

printf("%d\n", numb); //выводим значение numb на экран

}

double aver=(double)S/count; //считаем среднее значение

printf("Average=%lf\n", aver); //вывод среднего значения

fclose(in); //закрыть файл

}

else

printf("\nФайл не найден!");

return 0;

}

Чтение чисел из файла выполняется в переменную numb до тех пор, пока не будет достигнут конец файла. Одновременно ведется подсчет количества прочитанных чисел в переменной count и накопление суммы прочитанных чисел в переменной S. Переменные S и count целые, поэтому для правильного вычисления среднего арифметического, необходимо выполнить преобразование одной из этих переменных в формат double.

Функция fread() предназначена для чтения блоков данных из потока. Имеет прототип:

unsigned fread(void *ptr,unsigned size,unsigned n,FILE *fp);

Она читает n элементов данных, длиной size байт каждый, из заданного входного потока fp в блок, на который указывает указатель ptr. Общее число прочитанных байтов равно произведению n*size. При успешном завершении функция fread() возвращает число прочитанных элементов данных, при ошибке - 0.

Функция fwrite() предназначена для записи в файл блоков данных. Имеет прототип:

unsigned fwrite(void *ptr,unsigned size,unsigned n,FILE *fp);

Она добавляет n элементов данных, длиной size байт каждый, в заданный выходной файл fp. Данные записываются с позиции, на которую указывает указатель ptr. При успешном завершении операции функция fwrite() возвращает число записанных элементов данных, при ошибке - неверное число элементов данных.

Примеры использования функций fread()и fwrite() будут приведены позже при рассмотрении работы с бинарными файлами.

Рассмотрим другие библиотечные функции, используемые для работы с файлами:

1. Функции fseek( )и ftell().

Несмотря на то, что указатель позиции в файле перемещается автоматически, в языке С++ имеются функции fseek() и ftell(), позволяющие программно управлять положением позиции в файле.

Функция ftell() возвращает значение указателя текущей позиции файла.

Функция fseek() устанавливает указатель в позиция файла в соответ­ствии со значениями своих параметров.

Синтаксис данных функций следующий:

int fseek( FILE *stream, long offset, int origin );
long ftell( FILE *stream );

где *stream – указатель на файл; offset – смещение позиции в файле (в байтах); origin – флаг начального отсчета, который может принимать значения: SEEK_END – конец файла, SEEK_SET – начало файла; SEEK_CUR – текущая позиция. Последняя функция возвращает номер текущей позиции в файле.

Пример 6. Рассмотрим действие данных функций на примере считывания символов из файла в обратном порядке.
#include "stdafx.h"

#include

int main(void)
{
FILE *fp=fopen("my_file.txt","w"); //открытие файла для записи
if(fp != NULL)
{
fprintf(fp,"It is an example using fseek and ftell functions."); //запись в файл текста
}
fclose(fp); //закрытие файла
fp = fopen("my_file.txt","r"); //открытие файла для чтения
if(fp != NULL)
{
char ch;
fseek(fp,0L,SEEK_END); //указатель перемещен в конец файла
long length = ftell(fp);//определение размера файла
printf("length = %ld\n",length);
for(int i = 1;i <= length;i++) //цикл для чтения
{
fseek(fp,-i,SEEK_END); //перемещение на нужную позицию
ch = getc(fp);
putchar(ch);
}
}
fclose(fp);
return 0;
}

В данном примере сначала создается файл, в который записывается строка “It is an example using fseek and ftell functions.”. Затем этот файл открывается на чтение и с помощью функции fseek(fp,0L,SEEK_END) указатель позиции помещается в конец файла. Это достигается за счет установки флага SEEK_END, который перемещает позицию в конец файла при нулевом смещении. В результате функция ftell(fp) возвратит число символов в открытом файле. В цикле функция fseek(fp,-i,SEEK_END) смещает указатель позиции на –i символов относительно конца файла, после чего считывается символ функцией getc(), стоящий на i-й позиции с конца. Так как переменная i пробегает значения от 1 до length, то на экран будут выведены символы из файла в обратном порядке.

2. Функция ferror() позволяет проверить правильность выполнения последней операции при работе с файлами. Имеет следующий прототип:

int ferror(FILE *fp);

В случае ошибки возвращается ненулевое значение, в противном случае возвращается нуль.

3. Функция remove() удаляет файл и имеет следующий прототип:

int remove(char *file_name);

Здесь file_name - указатель на строку со спецификацией файла. При успешном завершении возвращается нуль, в противном случае возвращается ненулевое значение.

4. Функция rewind( ) устанавливает указатель текущей позиции в начало файла и имеет следующий прототип:

void rewind(FILE *fp);

Работа с текстовыми файлами


Файлы бывают текстовые (в которых можно записывать только буквы, цифры, скобки и т.п.) и двоичные (в которых могут храниться любые символы из таблицы). В текстовых файлах не употребляются первые 31 символ кодовой таблицы ASCII (управляющие), а символы конца строки 0x13 (возврат каретки, CR) и 0x10 (перевод строки LF) преобразуются при вводе в одиночный символ перевода строки \n (при выводе выполняется обратное преобразование). Эти символы добавляются в конце каждой строки, записываемой в текстовый файл. При обнаружении в текстовом файле символа с кодом 26 (0x26), т.е. признака конца файла, чтение файла в текстовом режиме заканчивается, хотя файл может иметь продолжение.

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

#include "stdafx.h"

#include

int main()

{ FILE *f, *r; // Указатели на файлы

char ch, pr[65];

char text[]="1,2,3,4,5 i caught a fish alive, 6,7,8,9,10 i let it go again!";

f=fopen("FIL1.txt","w"); // Создание нового файла FIL1.txt

fputs(text,f); // Запись в файл строки text

fclose(f); // Закрытие файла FIL1.txt

f=fopen("FIL1.txt","r");// Открытие файла FIL1.txt для чтения

r=fopen("FIL2.txt","w"); // Создание нового файла FIL2.txt

while (!feof(f)) // Пока не конец файла FIL1.txt

{ ch=fgetc(f); // Чтение символа в ch из файла FIL1.txt

if (ch >='a'&&ch<='z') // Прочитанный символ - буква?

fputc(ch,r); // Запись в файл FIL2.txt символа из ch

}

fclose(r); // Закрытие файла FIL2.txt

rewind(f); // Возврат указателя на начало файла FIL1.txt

fgets(pr,65,f); // Чтение из файла FIL2.txt строки в переменную pr

printf("%s\n",pr); // Вывод строки pr на дисплей

r=fopen("FIL2.txt","r"); // Открытие файла FIL2.txt для чтения

while (!feof(r)) // Пока не конец файла FIL2.txt

{ ch=fgetc(r); // Чтение символа из файла FIL2.txt

putchar(ch); // Вывод символа ch на дисплей

}

printf("\n");

fclose(f); // Закрытие файлов

fclose(r);

return 0;

}

Обработка бинарных файлов


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

Составим программу создания нового файла, каждая запись которого представляет собой структуру с информацией о городе: код, название, численность жителей.
#include "stdafx.h"

#include

typedef struct town

{ int kod;

char name[10];

long c; } city;// описание структуры записи о городе

city t; // опиание переменной такой структуры

int main()

{ char c;

FILE *f;

char ch;

f=fopen("file1.dat","wb");//открытие бинарного файла для записи

printf("\n Ввод информации о городе ");

do

{

printf("\nКод: "); scanf("%d", &t.kod);

printf("\nназвание: "); scanf("%s", t.name);

printf("\nколичество жителей: "); scanf("%ld", &t.c);

fwrite(&t, sizeof(t), 1, f);//запись в файл информации о городе

printf("\n END Закончить? y/n ");

ch=getch();

}

while (ch != 'y');

fclose(f);

}

Выполнение этой программы приведет к созданию бинарного файла с информацией о городах.

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

#include "stdafx.h"

#include

typedef struct town

{ int kod;

char name[10];

long c; } city;

city t;

int main()

{

FILE *f;

f=fopen("file1.dat","rb"); //открытие бинарного файла для чтения

fread(&t, sizeof(t), 1, f); //чтение из файла одной записи в t

while (!feof(f))

{

if(t.c>1000000)

printf("\n%3d название:%10s количество жителей:%ld",

t.kod, t.name, t.c);

fread(&t, sizeof(t), 1, f);

}

fclose(f);

}

7.3 Работа с потоками в С++


Поток — это понятие, относящееся к любому переносу данных от источника к приемнику. Потоки C++ обеспечивают надежную работу как со стандартными, так и с определенными пользователем типами данных.

Для работы с файлами в С++ необходимо подключить заголовочный файл В  определены несколько классов и подключены заголовочные файлы файловый ввод и    - файловый вывод.

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

Например, необходимо создать текстовый файл и записать в него строку «Работа с файлами в С++» средствами работы с потоками. Для этого необходимо проделать следующие шаги:

  1. создать объект класса ofstream;

  2. cвязать объект класса с файлом, в который будет производиться запись;

  3. записать строку в файл;

  4. закрыть файл.

#include "stdafx.h"

#include

#include

using namespace std;

  int main(int argc, char* argv[])

{ setlocale(0,"RUS");

  ofstream fout("cppstudio.txt"); /* создаём объект класса ofstream для записи и связываем его с файлом cppstudio.txt */

  fout<< "Работа с файлами в С++";// запись строки в файл

    fout.close(); // закрываем файл

    cout<<"Файл создан"<<"\n";

    return 0;

}

Для более углубленного изучения данного подхода работы с файлами рекомендуем обратиться, например, [2],[4].

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

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

  2. Встроенные функции языка Си, используемые для обработки строк.

  3. Назначение функции fgets(), fputs().

  4. Назначение функции fgetc(), fputc().

  5. Назначение функции fscanf(), fprintf().

  6. Обобщенная схема работы с файлами

  7. Режимы открытие файла

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

  9. Назначение функции fseek().


1   ...   18   19   20   21   22   23   24   25   26

Раздел 8 Подпрограммы


8.1 Структура сложной программы

8.2 Функции

8.3 Механизмы замены параметров

8.4 Перегрузка функций в С++

8.5 Рекурсия

8.6 Технология сборки библиотеки



8.1 Структура сложной программы


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

  1. Экономия памяти. Каждая подпрограмма записывается в программе один раз, в то время как обращаться к ней можно многократно из разных точек программы.

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

В языке С++ существует один вид подпрограмм, который называется функция.

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

Каждая программа на языке С++ должна иметь главную функцию (main), которая служит точкой входа в программу. Кроме главной функции в программе может быть оформлено произвольное число подпрограмм-функций. Создаваемая подпрограмма-функция должна иметь следующую структуру:
ЗАГОЛОВОК

{

Тело функции

}
Заголовок функции называется ее объявлением, а тело функции называется ее описанием. Любая подпрограмма-функция должна быть объявлена и определена.

Заголовок подпрограммы-функции должен иметь следующую структуру:
тип имя_функции ( [ список параметров])
Рассмотрим составные части заголовка.

Тип – это тип возвращаемого функцией значения. Он может быть любым(int, float, char, указатель на массив или другую функцию). Если функция не должна возвращать никакого значения, указывается тип void (пусто). Если никакой тип не указан, по умолчанию считается тип int.

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


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

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

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

#include "stdafx.h"

ЗАГОЛОВОК

{

тело функции

}



main()//начало главной функции

{…

имя-функции (параметр1, параметр2,…); /*обращение к подпрограмме-функции */



} //конец главной функции

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

Прототип функции по форме аналогичен заголовку функции, но в конце которого ставится ";". Второй вариант компоновки программы, содержащей подпрограмму-функцию, будет выглядеть так:
#include "stdafx.h"

ЗАГОЛОВОК;
main() //начало главной функции

{…

имя-функции (параметр1, параметр2,…); /*обращение к подпрограмме-функции */



} //конец главной функции
ЗАГОЛОВОК

{

тело функции

}

8.2 Функции


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

Общий вид описания функции


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

Тип Имя_функции(список формальных параметров)

{

Описание локальных переменных;

Операторы тела функции;

return результат;

}

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

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

void имя_функции(список формальных параметров)

{

Описание локальных переменных;

Операторы тела функции;

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

#include "stdafx.h"

int maximum(int a, int b) //заголовок функции maximum

{

int c; //локальная переменная

if (a>b)

c=a;

else

c=b;

return c; // возвращение результата

}
void main()

{ int x,y,z;

printf("Введите x и y:");

scanf("%d%d",&x,&y); // ввод двух чисел

z=maximum(x,y); // обращение к функции maximum

printf("max=%d\n",z);

}

Рассмотрим пример программы, использующей нетипизированную функцию. Функция Form_matrix будет заполнять целочисленную матрицу размера mxn случайными числами.

#include "stdafx.h"

#include "stdlib.h"

#define M 50

void Form_matrix(int A[][M], int m, int n) /*заголовок функции Form_matrix */

{

int i,j; //локальные переменные

for(i=0;i<m;i++)

for(j=0;j

A[i][j]=rand()%100-50;

}

void main()

{ int m1,n1,m2,n2; //переменные для задания размерности матриц

int Matr1[M][M],Matr2[M][M]; /*объявление двух матриц размера 50х50 */

printf("Введите размерность Mart1 ");

scanf("%d%d",&m1,&n1); // ввод двух чисел

Form_matrix(Matr1,m1,n1); //обращение к функции Form_matrix

printf("Введите размерность Mart2 ");

scanf("%d%d",&m2,&n2); // ввод двух чисел

Form_matrix(Matr2,m2,n2); //обращение к функции Form_matrix



}

Данный пример демонстрирует использование функции Form_matrix дважды в главной функции. При первом обращении к функции произойдет заполнение матрицы Mart1, а при втором обращении – Matr2, так как их имена указаны в соответствующих обращениях к функции. Функция Form_matrix может заполнить матрицу любого размера, не превышающего 50х50. (Конечно, можно было создать динамические матрицы, но это другая история, и мы говорили о ней в параграфе «Динамическая память»).

В теории о подпрограммах-функциях следует остановиться еще на трех важных вопросах:

  • обращение к нетипизированной и типизированной функциям;

  • передача параметров в функцию;

  • возвращение результатов.

Обращение к функции


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

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

printf("max=%d\n", maximum(x,y));

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

Пример программы с функцией


Вычислить значение: Z= ,

где а - заданное вещественное число.

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



где i – номер шага вычисления (умножения);

n – число шагов.

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

#include "stdafx.h"

float ST(float x, int n) // начало функции ST

{

int i;

float P; //локальные переменные i и P

P=1;

for( i=1; i<= n; i++)

P = P*x; //накопление произведения

return P;

} // конец функции ST

void main()

{

float a,Z;

printf("Введите число а:");

scanf("%f",&a);

Z = (ST(a, 5) + ST(1/a, 5))/(2* ST(a, 7));

printf("Z=%f\n", Z);

}

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

Предыдущую программу можно скомпоновать так:

#include "stdafx.h"

float ST(float , int ); // прототип функции ST

void main()

{ float a,Z;

printf("Введите число а:");

scanf("%f",&a);

Z = (ST(a, 5) + ST(1/a, 5))/(2* ST(a, 7));

printf("Z=%f\n", Z);

}

// текст функции ST

float ST(float x, int n)

{

int i;

float P;

P=1;

for( i=1; i<= n; i++)

P = P*x;

return P;

}
Передача параметров в функцию

Механизм передачи параметров является основным способом обмена информацией между вызывающей и вызываемой функциями. Напомним, что параметры, перечисленные в заголовке функции, называются формальными, а параметры, указываемые при вызове функции – фактическими. В приведенном выше примере
Z = (ST(a, 5) + ST(1/a, 5))/(2* ST(a, 7));
при обращении к функции ST параметры a, 5, 1/a, 7 – фактические данные, с которыми будет работать функция ST в каждом своем вызове.

В заголовке функции ST
float ST(float x, int n)

x и n - это формальные параметры, которые примут в себя копии значений фактических параметров.

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

8.3 Механизмы замены параметров


В языке С++ существует два механизма передачи параметров в функции: по значению и по адресу.

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

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

Рассмотрим два примера, иллюстрирующих механизмы передачи параметров:

Пример 1Пример 2

#include "stdafx.h" #include "stdafx.h"

void Z (int у) void Z (int *у)

{ {

y=l; *y=1;

} }

void main() void main()

{ int х; { int х;

x=0; х=0;

Z(x);//обращение к функции Z Z(&x);//обращение к функции Z

printf("x=%d", x); printf("x=%d", x);

} }
В примере 1 функция Z() содержит формальный параметр у, который передается по значению, поэтому его измене­ние в процедуре (у=1;) не влияет на значение фактического параметра х. После выполнения программы на экран будет выведено: х=0.

В примере 2 у функции Z() формальный параметр у – это указатель. В него передается при вызове функции Z() адрес фактического параметра x. Это означает, что функция Z() изменяет значение y в той же ячейки памяти, где находится значение фактического параметра x . На экран будет выведено:

х = 1.

Параметры-массивы в функциях


Массивы, так же как и простые переменные, можно передавать в функции в качестве параметров. Так как имя массива – это адрес, то передача массива происходит всегда по адресу.

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

#include "stdafx.h"

int Sum ( int A[], int N )//заголовок функции

{

int i, sum; //локальные переменные

sum = 0;

for ( i = 0; i < N; i ++ )

sum += A[i];

return sum/N; //возвращаемое значение

}

void main()

{

int x[5]={1,2,3,4,5},

y[3]={11,22,33};

printf("\n sr x=%d sr y=%d\n", Sum(x,5),Sum(y,3));

}

Обратите внимание, что в заголовке функции Sum размер N массива указан отдельным параметром. Нельзя объявлять массив-параметр как A[N], а только как A[]или *A.

Если в функцию передаётся двумерный массив, то описание соответствующего параметра функции должно содержать количество столбцов; количество строк - несущественно, поскольку фактически передаётся указатель. Например, так: int Х[ ][5], или Х[5][5].

Рассмотрим пример функции, перемножающей матрицы А и В; результат - матрица С. По правилам математики перемножать можно матрицы, размеры которых (mxn) и (nxk) соответственно. Результирующая матрица будет иметь размеры (mxk).

const nmax = 50;

void product(int А[][nmax], int В[][nmax],int С[][nmax], int m, int n, int k)

{
/* m - число строк в матрице А;
    n - число строк в матрице В и число столбцов в матрице А;
    k - число столбцов в матрице В.  */

for (int i=0; i< m; i++)
     for (int j=0; j< k; j++)


{
     
С[i][j]=0;
     for (int l=0; l< n; l++)


С[i][j] + = А[i][l]*В[l][j];
}
}

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

В приведённом примере есть недостаток - здесь заранее фиксируется максимальная размерность матриц. Но использоваться может только часть памяти.

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

Возвращение результатов


Результат работы функции возвращается в точку вызова с помощью оператора

return [выражение];

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

Теория создания функций, рассмотренная в данном параграфе, является базовой и будет достаточной для начинающих программистов. Для более глубоко изучения данного вопроса следует обратиться, например [4]. Но, даже изучив теорию в таком объеме, у нас есть возможность научить вас собирать собственные библиотечные файлы.

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


Задача 1

Даны два вектора: = {хi}; i = и ={yi};i= .

Вычислить значение: D = , где ; ;

тх, ту - максимальные компоненты векторов и соответственно;

sx, sy - средние значения компонент векторов и соответственно.

Решение:

#include "stdafx.h"

#include

float Mod_Otk(float *a, int n) /* типизированная функция для нахождения максимального компонента и среднего значения в любом массиве */

{

float maxi, sa, Da; //описание локальных переменных

int i;

maxi =-10000; 

sa=0;

for (i =0;i

{

if (a[i]>maxi) maxi= a[i];

sa += a[i];

}

sa = sa/n;

Da= fabs(maxi - sa);

return Da;

}
void main()

{ float X[10],Y[10];

int i;

float Dx, Dy, D;

printf("Bведитe массив X:\n");

for (i =0;i<8;i++)

scanf("%f",&X[i]);

printf("Bведитe массив Y:\n");

for (i =0;i<10;i++)

scanf("%f",&Y[i]);

Dx = Mod_Otk(X, 8);//вызов функции Mod_Otk для массива X

Dy = Mod_Otk(Y,10);//вызов функции Mod_Otk для массива Y

D = Dx/Dy;

printf("D=%f\n",D);

}
Задача 2

Даны две матрицы: А = {a i j }5x6 и В = {bij}4x7.

Вычислить разность: С = КА - KB, где КА и KB- количество положительных элементов в матрицах А и В соответственно.

#include "stdafx.h"

int CP(float D[7][7], int m, int n) /*типизированная функция для подсчета количества положительных элементов в любой матрице */

{ int i, j, KD;

KD=0;// инициализация счетчика

for (i=0;i

for (j=0;j

if (D[i][j]>0) KD ++; /*добавление в счетчик единицы, если элемент матрицы окажется >0 */

return KD; // возвращение результата в точку вызова

}
int main()

{

float A[7][7], B[7][7];

int i,j, C;

printf("Введите матрицу А\n");

for (i=0;i<5;i++)

for (j=0;j<6;j++)

scanf("%f",&A[i][j]);

printf("Введите матрицу B\n");

for (i=0;i<4;i++)

for (j=0;j<7;j++)

scanf("%f",&B[i][j]);
C= CP(A, 5,6)- CP(B, 4, 7); //вызовы функции СР

printf("C=%d\n", C);

return 0;

}
Задача 3

На плоскости декартовыми координатами заданы 10 точек:

{x1,y1},{x2,y2}, ...,{х1010}.

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

, где а иb -декартовы координаты точки.

Решение:

#include "stdafx.h"

#include
void PK(float a, float b, float *ro, float *fi)

/* безтиповая функция для расчета полярных координат точки */

{

*ro = sqrt(a*a + b*b);

*fi = atan(b/a);

}
int main()

{

float X[10], Y[10]; // масcивы для декартовых координат точек

float R[10], F[10]; // масcивы для полярных координат точек
int i, N;

float maxR;

printf("Введите абсциссы 10 точек\n");

for (i=0;i<10;i++) scanf("%f",&X[i]);

printf(" Введите ординаты 10 точек\n");

for (i=0;i<10;i++) scanf("%f",&Y[i]);

maxR = 0;

for (i=0;i<10;i++)

{

PK(X[i],Y[i],&R[i],&F[i]);

if (R[i]>maxR) // поиск максимального радиуса

{

maxR =R[i];

N=i; /*запоминаем номер точки, радиус которой больше, чем у предыдущих */

}

}

printf("romax=%f fimax=%f\n", R[N],F[N]);/* вывод полярных координат точки с номером N */

return 0;

}
Задача 4

Для заданных квадратных матриц: A = {aij}3x3и В = {bi j}4х4 вычислить симметричные им матрицы по правилу:

, x- матрица , симметричная матрице y.

Решение:

#include "stdafx.h"
void SM(float Y[4][4], int n, float X[4][4])/*безтиповая функция вычисления симметричной матрицы X из исходной матрицы Y */

{

int i,j;

for (i=0;i

for (j=i;j

{

X[i][j]=(Y[i][j] + Y[j][i])/2;

X[j][i] =X[i][j];

}

}

void VIVOD(float Y[4][4], int n)//функция вывода матрицы

{for (i=0;i

{for (j=0;j

printf("\n");

}

}

void main()

{

float A[4][4], B[4][4], C[4][4], D[4][4];

int i, j;

printf("Введите матрицу А\n");

for (i=0;i<3;i++)

for (j=0;j<3;j++) scanf("%f",&A[i][j]);

printf("Введите матрицу B\n");

for (i=0;i<4;i++)

for (j=0;j<4;j++) scanf("%f",&B[i][j]);

SM(A, 3,C); // обращение к функции SM для матрицы A

SM(B, 4, D); //обращение к функции SM для матрицы B

printf("Симметричная матрица С\n");

VIVOD(C,3);

printf("Симметричная матрица D\n");

VIVOD(D,4);

}

8.4 Перегрузка функций в С++


Перегруженная функция – это функция, которая позволяет при обращении к себе варьировать типы передаваемых параметров. Цель перегрузки состоит в том, чтобы функция с одним и тем же именем возвращала разного типа значение при обращении к ней с различными типами фактических параметров. Рассмотрим этот механизм на примере некоторой абстрактной функции с именем SUM. Допустим, мы имеем три варианта функции SUM.

float SUM (float a, float b);

//принимает два вещественных аргумента и возвращает результат ввиде вещественного числа
double SUM (double a, double b);

//принимает два аргумента вещественного длинного типа и возвращает результат ввиде вещественного длинного числа
complex SUM (complex a, complex b);

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

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

#include "stdafx.h"
#define complex struct compl

complex

{double x,y;};
complex SUM (complex a, complex b)

{complex c;

c.x=a.x+b.x;

c.y=a.y+b.y;

return c;

}

float SUM (float a, float b)

{float c;

c=a+b;

return c;

}

double SUM (double a, double b)

{ double c;

c=a+b;

return c;

}

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

{complex z,m,n;

float a=4.5,b=6.5;

z.x=5; z.y=6;

m.x=7;m.y=8;

n= SUM (z,m); //вызов функции SUM для комплексных параметров

printf("%lf+i%lf\n",n.x,n.y);

float d= SUM (a,b); //вызов функции SUM для вещественных параметров

printf("d=%f\n",d);

float d2= SUM (10,35); //неоднозначный вызов функции SUM

printf("d2=%f\n",d2);
return 0;

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

По типам фактических параметров компилятор определяет, какую именно функцию требуется вызвать. Этот процесс называется разрешением перегрузки (перевод английского слова resolution в смысле «уточнение»). Тип возвращаемого функцией значения в разрешении не участвует. Механизм разрешения основан на достаточно сложном наборе правил, смысл которых сводится к тому, чтобы использовать функцию с наиболее подходящими аргументами или выдать сообщение, если такой не найдется. Если точного соответствия не найдено, выполняется преобразование типов параметров по общим правилам, например char в int; int во float, float в double; и т.п. Если соответствие может быть получено более чем одним способом, вызов считается неоднозначным и выдается сообщение об ошибке. В нашем примере это продемонстрировано вызовом третьим, когда в функцию SUM передаются в качестве параметров два целых числа 10 и 35. Эти параметры могут быть преобразованы как в тип float, так и в тип double, что и вызовет возникновение ошибочной неоднозначности.

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

• Перегруженные функции должны находиться в одной области видимости,

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

• Перегруженные функции могут иметь параметры по умолчанию, при этом

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

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

• Функции не могут быть перегружены, если описание их параметров отличается только модификатором const (например, int и const int ), или использованием ссылки (например, int и int&).

Более подробную информацию о перегруженных функциях см. в [2].

8.5 Рекурсия


В теле функции известны все объекты, описанные во внешнем блоке, т.е. все глобальные переменные и имя самой функции.

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

Рекурсия возможна благодаря тому, что при вызове функции создаются новые экземпляры локальных переменных, которые сохраняются во внутреннем стеке машины. Стек функционирует по принципу LIFO - Last In – First Out (последний вошел – первый вышел).

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

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

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

Рассмотрим пример вычисления факториала 5.

, где - это 4!

т.е 5!=4! 5

Факториал нуля равен 1. Отсюда формула вычисления N-факториала:


Реализуем вычисление факториала в виде функции:

#include "stdafx.h"

float fact(int N) //рекурсивная функция вычисления факториала числа N


Обращение функции к самой себе
{

if (N==0)

return 1;

else

return (fact(N-1)*N);

}

void main()

{ int N=15;

printf("факториал 15=%f\n",fact(N)); /* обращение к функции fact для вычисления факториала 15 */

}

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

Пример: Вычислить количество нулей в массиве А[10].

# include "stdafx.h"

const int n=10;

int kol(int i,int *A)

{ if (i==n) return 0;

else {

if(A[i]==0) return kol(i+1,A)+1;

else return kol(i+1,A);

}

}

int main()

{ int y[]={1,0,2,5,4,0,1,3,0,4,3};

int x=kol(0,y);

printf("количество нулей=%d\n",x);

}

8.6 Технология сборки библиотеки



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

Заголовочный файл (иногда головной файл, англ. header file), или подключаемый файл, в языках программирования С и C++ - это файл с расширением .h. Заголовочный файл в общем случае может содержать любые конструкции языка программирования, но на практике в него помещают объявления идентификаторов, которые должны быть объявлены более чем в одном файле вашей программы, объявления структур, прототипы функций, перечисления, макросы препроцессора. Основная цель использования заголовочных файлов — вынесение описания нестандартных типов и функций за пределы основного файла с кодом. Заголовочный файл используется путём включения его текста в использующий его файл директивой препроцессора #include. Чтобы избежать повторного включения одного и того же кода, используются директивы #ifndef, #define, #endif.

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

Пусть создаваемая нами библиотека состоит из заголовочного файла mylib.h и файла mylib.cpp.

В заголовочном файле mylib.h содержатся прототипы функций, которые описаны в данном параграфе.

Перечислим все эти функции:

  • maximum(). Находит и возвращает наибольшее из двух чисел.

  • Form_matrix(). Заполняет матрицу, адрес которой передается ей в качестве параметра, случайными числами.

  • ST(). Возводит любое число в степень n.

  • Z(). Меняет значение переданного ей параметра на случайное число.

  • Sum(). Вычисляет среднее арифметическое вектора, адрес и размер которого передаются в качестве параметров.

  • Product(). Вычисляет произведение двух матриц, адреса и размеры которых передаются в качестве параметров. Возвращает матрицу соответствующего размера.

  • SM(). Безтиповая функция вычисляет симметричную матрицу из исходной матрицы.

  • PK(). Безтиповая функция переводит декартовые координаты точки в полярные.

  • CP().Типизированная функция для подсчета количества положительных элементов в любой матрице.

  • Mod_Otk(). Типизированная функция находит максимальный компонент и среднее значение в любом массиве.

  • fact(). Рекурсивная функция вычисляет факториал числа n.

Текст файла mylib.h:

#ifndef MYLIB_H // если MYLIB_H еще не определили, то определяем

#define MYLIB_H

const nmax = 50; // максимальная размерность матрицы

int maximum(int a, int b);//прототип функции maximum

void Form_matrix(int A[][M], int m, int n); /*прототип функции Form_matrix */

float ST(float x, int n); //прототип функции ST

void Z (int у); //прототип функции Z

void Z (int *у); //прототип функции Z

int Sum ( int A[], int N ); //прототип функции Sum

void product(int А[][nmax], int В[][nmax],int С[][nmax], int m, int n, int k); //прототип функции product

void SM(float Y[4][4], int n, float X[4][4]); /*прототип функции SM */

void PK(float a, float b, float *ro, float *fi); /*прототип функции PK */

int CP(float D[7][7], int m, int n); //прототип функции CP

float Mod_Otk(float *a, int n); //прототип функции Mod_Otk

float fact(int N); //прототип функции fact

#endif /* MYLIB_H */
Файл mylib.cpp является созданной нами библиотекой, в которой содержатся реализации всех перечисленных выше функций.

В целях экономии текст файла mylib.cpp приведем не полностью.

Текстфайлаmylib.cpp:

#include "stdafx.h"

#include "stdlib.h"

{

int Sum ( int A[], int N )//заголовок функции Sum

{

int i, sum; //локальные переменные

sum = 0;

for ( i = 0; i < N; i ++ )

sum += A[i];

return sum/N; //возвращаемое значение

}

void product(int А[][nmax], int В[][nmax],int С[][nmax], int m, int n, int k) //заголовок функции product

{
/* m - число строк в матрице А;
    n - число строк в матрице В и число столбцов в матрице А;
   k - число столбцов в матрице В.  */

for (int i=0; i< m; i++)
      for (int j=0; j< k; j++)


{
     
С[i][j]=0;
      for (int l=0; l< n; l++)


С[i][j] + = А[i][l]*В[l][j];
}
}

float fact(int N) //рекурсивная функция вычисления факториала числа N

{

if (N==0)

return 1;

else

return (fact(N-1)*N);



}

Текст файла, использующего созданную библиотеку

#include "mylib.h"//подключение заголовочного файла библиотеки mylib

// главная функция выполняет основную работу программы

int main()

{

int a[nMax][nMax],b[nMax][nMax]; //объявление матриц



// здесь могут быть обращения к функциям библиотеки

return 0;

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

  1. Типы функции, используемые в программах на языке Си.

  2. Структура функции, определенной пользователем.

  3. Отличие типовой функции от безтиповой функции.

  4. Типы параметров функции.

  5. Глобальные и локальные идентификаторы.

  6. Для чего используются подпрограммы?

  7. Структура безтиповой функции, определенной пользователем.

  8. Правила взаимодействия списков фактических и формальных параметров.

  9. Отличие параметров-значений от параметров переменных.


1   ...   18   19   20   21   22   23   24   25   26