Листинг – что это такое простыми словами: полный разбор понятия. Оформление листингов программ

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

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

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

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

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

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

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

Пример оформления приведен в листинге 3.1.

Листинг 3.1 – Программа «Hello, World!»

#include

// Вывод строки в стандартный поток вывода

cout << "Hello World!";

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

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

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

Курсовая работа (отчет по преддипломной практике) защищается на заседании создаваемой кафедрой рабочей комиссии, на которое является студент с курсовой работой (отчетом по преддипломной практике). На доклад по курсовой работе (отчету по преддипломной практике) отводится до 10 минут. Доклад может сопровождаться иллюстративным материалом (плакатами, компьютерной презентацией и/или демонстрацией программных средств на ЭВМ).

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

При выставлении оценки за курсовую работу учитываются:

– степень решенности поставленной задачи;

– степень самостоятельности и инициативности студента;

– умение студента пользоваться литературными источниками;

– степень соответствия пояснительной записки требованиям по её офор­м­лению;

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

Дипломная работа

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

– актуальность темы,

– степень решенности поставленной задачи,

– степень самостоятельности и инициативности студента,

– умение студента пользоваться специальной литературой,

– способности студента к инженерной и исследовательской работе,

– возможность использования полученных результатов на практике,

– возможности присвоения выпускнику соответствующей квалификации.

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

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

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

Дипломная работа, допущенная кафедрой к защите, направляется заведующим кафедрой на рецензию.

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

В рецензии должны быть отмечены:

– актуальность темы дипломной работы;

– степень соответствия дипломной работы заданию;

– логичность построения описательной части дипломной работы;

– наличие по теме дипломной работы критического обзора литературы, его полнота и последовательность анализа;

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

– наличие аргументированных выводов по результатам дипломной работы;

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

– недостатки и слабые стороны дипломной работы;

– замечания по оформлению описательной части дипломной работы и стилю изложения материала;

– оценка дипломной работы (в соответствии с принятой системой оценок).

Рецензент имеет право затребовать у студента – автора дипломной работы дополнительные материалы, касающиеся существа проделанной работы. Студент должен быть ознакомлен с рецензией до защиты работы в ГЭК. Подписи руководителей и рецензентов, не являющихся сотрудниками ВГУ, должны быть заверены отделом кадров организации, где они работают.

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

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

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

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

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

Дипломная работа после защиты хранится в вузе, в котором она выполнялась, на протяжении пяти лет.

Приложение А
Пример оформления титульного листа курсовой работы

Приложение Б
Пример оформления титульного листа отчета о производственной практике

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

Приложение Г
Бланк задания на дипломную (курсовую) работу

УО «Витебский государственный университет им. П.М. Машерова»

ЗАДАНИЕ
на дипломную работу

Студенту ____ курса

Фамилия И.О.

1. Тема работы

2. Срок сдачи студентом законченной работы

3. Исходные данные к работе

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

5. Перечень графического или программного материала (с точным указанием обязательных чертежей) или модулей программы

6. Консультанты по работе с указанием относящихся к ним разделов

7. Дата выдачи задания «___» ____________ 20___г.

Руководитель ______________ / ____________ /

подпись Фамилия И.О.

Задание принял к исполнению «___» ___________ 20___г.

________________________________

подпись студента

Приложение Д
Пример оформления реферата дипломной работы

РЕФЕРАТ

Дипломная работа, 56 стр., 4 ил., 2 табл., библиогр. 16.

СЛОЖНЫЕ СИСТЕМЫ, МАТЕМАТИЧЕСКОЕ И ИМИТАЦИОННОЕ МОДЕЛИРОВАНИЕ, ОПТИМИЗАЦИЯ, УСТОЙЧИВОСТЬ, СТОХАСТИКА, ДЕКОМПОЗИЦИЯ, КОМБИНАТОРИКА

Объект исследования – вычислительные и информационные процессы и системы. Цель работы – разработка теоретических основ моделирования, анализа и эффективной организации вычислительных и информационных процессов и систем.

Методы исследования – методы теории вероятностей, математической статистики, массового обслуживания и надежности, логико-комбинаторные методы, имитационное моделирование.

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

Областью применения являются процессы автоматизированного анализа и синтеза сложных систем.

Приложение Е
Пример оформления перечня условных обозначений и сокращений

ОбозначениЯ и сокращениЯ

БИС – большая интегральная схема

ИС – интегральная схема

СБИС – сверхбольшая интегральная схема

ПЛМ – программируемая логическая матрица

ГСП – генератор случайных последовательностей

ГПП – генератор псевдослучайных последовательностей

СЛН – средства локализации неисправностей

Приложение Ж
Примеры описаний использованных источников

Таблица Ж.1 – Примеры описания самостоятельных изданий

Характеристика источника Пример оформления
Один, два или три автора Орлов, С.А. – Технологии разработки программного обеспечения: Учебник для вузов / С.А. Орлов. – СПб.: Питер, 2002. – 464 с.
Биячуев, Т.А. Безопасность корпоративных сетей / Т.А. Бия­чуев; под ред. Л.Г. Осовецкого. – СПб: СПб ГУ ИТМО, 2004. – 161 с.
Дейтел, Х.М. Как программировать на С++ / Х.М. Дейтел, П.Дж. Дейтел. – М.: Бином, 2001. – 1152 с..
Митчелл М. Программирование для Linux. Профессиональный подход. / М. Митчелл, Дж. Оулдем, А. Самъюэл. – М.: Издательский дом «Вильямс», 2003. – 288 с.
Бахвалов, Н.С. Численные методы: учеб. пособие для физ.-мат. специальностей вузов / Н.С. Бахвалов, Н.П. Жидков, Г.М. Кобельков; под общ. ред. Н.И. Тихонова. – 2-е изд. М.: Физматлит, 2002. – 630 с.
Четыре и более авторов Приемы объектно-ориентированного проектирования. Паттерны проектирования / Гамма Э. [и др.]. – СПб.: Питер, 2008. – 366 с.
Прикладная механика: учеб. пособие / А. Т. Скойбеда [и др.]; под общ. ред. А.Т. Скойбеды. – Мн.: Вышэйшая школа, 1997. – 522 с.
Многотомное издание Архангельский, А.Я. C++ Builder 6: справочное пособие: в 2 кн. / А.Я. Архангельский. – М.: Бином-Пресс, 2002. – 2 кн.
Кнут, Д. Искусство программирования для ЭВМ: в 3 т. / Д. Кнут. – М.: Мир, 1976–1978. – 3 т.
Отдельный том в многотомном издании Архангельский, А.Я. C++ Builder 6: справочное пособие: в 2 кн. Кн. 1. Язык С++ / А.Я. Архангельский. – М.: Бином-Пресс, 2002. – 544 с.

Продолжение таблицы Ж.1

Архангельский, А.Я. C++ Builder 6: справочное пособие: в 2 кн. Кн. 2. Классы и компоненты / А.Я. Архангельский. – М.: Бином-Пресс, 2002. – 528 с.
Сборник статей, трудов Инновационные технологии в учебно-воспитательном процессе УО «ВГУ им. П.М. Машерова»: сб. ст. / Вит. гос. ун-т им. П.М. Машерова; редкол. А.В. Русецкий (гл. ред.) [и др.]. – Витебск, 2006. – 111 с.
Современные информационные компьютерные технологии: сб. науч. ст.: в 2 ч. / Гродн. гос. ун-т им. Я.Купалы; ред­кол.: А.М. Кадан (отв. ред.) [и др.]. – Гродно, 2008. – 2 ч.
Материалы конференций Информатизация обучения математике и информатике: педагогические аспекты: материалы междунар. науч. конф., посвящ. 85-летию Белорус. гос. ун-та, Минск, 25–28 окт. 2006 г. / Белорус. гос. ун-т; редкол.: И.А. Новик (отв. ред.) [и др.]. – Мн., 2006. – 499 с.
II Машеровские чтения: материалы региональной научно-практич. конф. студентов, магистрантов и аспирантов, Витебск, 24–25 апр. 2007 г.: в 2 т. / Вит. гос. ун-т. – Витебск, 2007. – 2 т.
Стандарт ГОСТ 19.701–90. Единая система программной до­ку­мен­та­ции. Схемы алгоритмов, программ, данных и систем. Условные обозначения и правила выполнения. – Взамен ГОСТ 19.002–80, ГОСТ 19.003–80; введ. 01.01.1992. – М.: Изд-во стандартов, 1991. – 26 с.
ГОСТ Р 50922–2006. Защита информации. Основные термины и определения. – Взамен ГОСТ Р 50922–96; введ. 01.02.2008. – М.: Стандартинформ, 2008. – 7 с.
Электронные ресурсы Microsoft Visual Studio [Электронный ресурс]: Express Edition / Microsoft Corporation, ComputerPress. – Электрон. дан., электрон. текстовые дан. и прогр. – 1 эл. опт. диск.
MSDN Library [Электронный ресурс]: Справочная система. – Microsoft Corporation, 2004. – 3 эл. опт. диска (CD-ROM).
Мир ПК [Электронный ресурс]. – М.: Открытые системы. – Приложение к Мир ПК (журнал). – 2006. – №2. – 1 эл. опт. диск (CD-ROM).

Продолжение таблицы Ж.1

Таблица Ж.2 – Примеры описания составных частей изданий

Характеристи­ка источника Пример оформления
Составная часть книги Либерти, Д. Анализ и проектирование объектно-ориен­ти­ро­ванных программ / Д. Либерти // Освой самостоятельно C++ за 21 день / Д. Либерти. – М.: Вильямс, 2000. – С.561–595.
Свердлов, С.З. Языки и эволюция технологий программирования / С.З. Свердлов // Языки программирования и методы трансляции: учеб. пособ. / С.З. Свердлов. – СПб.: Питер, 2007. – С. 17–205.
Глава из книги Вирт, Н. Динамические информационные структуры / Н. Вирт // Алгоритмы + структуры данных = программы / Н. Вирт. – М.: Мир, 1985. – Гл. 4. – С.189–318.
Хендерсон, К. Построение приложений для работы с базами данных / К.Хендерсон // Borland C++ Builder / К. Рейс­дорф, К. Хендерсон. – М.: Бином, 1998. – Гл. 18. – С. 583–595.
Составная часть сборника Русецкий, А.В. Главная задача – внедрение новых образовательных технологий / А.В. Русецкий // Инновационные технологии в учебно-воспитательном процессе УО «ВГУ им. П.М. Машерова»: сб. ст. / Вит. гос. ун-т им. П.М. Машерова; редкол. А.В. Русецкий (гл. ред.) [и др.]. – Витебск, 2006. – С. 3–4.
Буза, М.К. Параллельная обработка одного класса арифметических выражений / М.К. Буза, Лю Цзяхуэй // Современные информационные компьютерные технологии: сб. науч. ст.: в 2 ч. / Гродн. гос. ун-т им. Я.Купалы; редкол.: А.М. Кадан (отв. ред.) [и др.]. – Гродно, 2008. – Ч.1. – С. 7–9.

Продолжение таблицы Ж.2

Статья из сборников тезисов докладов и материалов конференций Смоляк, В.А. Компьютерные модели клеточных автоматов / В.А. Смоляк // II Машеровские чтения: материалы региональной научно-практич. конф. студентов, магистрантов и аспирантов, Витебск, 24–25 апр. 2007 г.: в 2 т. / Вит. гос. ун-т. – Витебск, 2007. – Т. 1. – с.116–117.
Статья из журнала Муравьев, И. CMS Drupal и ее особенности / Илья Муравьев // Сетевые решения. – 2007. – № 5. – С. 26–30.
Ярмолик, С.В. Стеганографические методы защиты информации / С.В. Ярмолик, Ю.Н. Листопад // Информатизация образования. – 2005. – № 1. – С. 64–74.
Статья из газеты Станкевич, В. Две модели JSP / В. Станкевич // Компьютерные вести. – 2008. – 30 окт. – С. 23.
Статья из энциклопедии, словаря Першиков, В.И. Программа / В.И. Першиков, В.М. Са­вин­ков // Толковый словарь по информатике. – М.: Финансы и статистика, 1991. – С. 296–303.
Компьютер // Толковый словарь по вычислительным системам / Под ред. В. Иллингуорта [и др.]. – М.: Машиностроение, 1991. – С. 92.
Ресурсы удаленного доступа Обзор SQL Server Express // Microsoft TechNet [Электронный ресурс] / Microsoft Corporation. – 2008. – Режим доступа: http://technet.micro­soft.com/ru-ru/library/ms165588(SQL. 90).aspx. – Дата доступа: 15.01.2009.
Jones, J. Abstract Syntax Tree Implementation Idioms / Joel Jones // The 10th Conference on Pattern Languages of Programs 2003 . – 2003. – Mode of access: http://jerry.cs.uiuc.edu/~plop/plop2003/Papers/Jones-Imple­ment­ingASTs.pdf. – Date of access: 15.01.2009.

Приложение И
Пример описания содержания электронного носителя

На электронном носителе расположены следующие директории и файлы:

– Файл «ФИО-курс-Тема.doc» представляет собой текстовый документ с курсовой работой, дипломной или отчетом о преддипломной практике.

– Директория «Software» содержит программное обеспечение, необходимое для запуска проекта.

– Директория «Hello World Project» содержит исходный код проекта Hello World.

– Директория «Final Build 31-01-2009» содержит финальную версию исполняемых файлов проекта Hello World.

– Директория «User Manual» содержит руководство пользователя и справочную информацию.

– Директория «Presentation» содержит презентацию к защите.

– Файл «Readme.txt» содержит описание содержания электронного носителя.


Похожая информация.


Назначение

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

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

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

Программисты часто переносят исходный код из одного проекта в другой, что носит название повторного использования кода (Software reusability ).

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

Организация

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

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

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

Качество

В отличие от человека, для компьютера нет «хорошо написанного» или «плохо написанного» кода. Но то, как написан код, может сильно влиять на процесс сопровождения ПО . О качестве исходного кода можно судить по следующим параметрам:

  • читаемость кода (в том числе наличие или отсутствие комментариев к коду;
  • лёгкость в поддержке, тестировании, отладке и устранении ошибок, модификации и портировании;
  • низкая сложность;
  • низкое использование ресурсов - памяти, процессора, дискового пространства;
  • отсутствие замечаний, выводимых компилятором;
  • отсутствие «мусора» - неиспользуемых переменных, недостижимых блоков кода, ненужных устаревших комментариев и т. д.

// Лабораторная работа №6

// Индивидуальное задание №2

#include "stdafx.h"

#include

#include "conio.h"

#include "math.h"

#include "windows.h"

using namespace std;

int _tmain(int argc, _TCHAR* argv)

setlocale(LC_ALL, "Russian");

int nrow, ncol, i, j, summ;

cout<<"Лабораторная работа № 6\n";

cout<<"\nГорошко А.А., БАС-051\n";

cout<<"\nВариант № 6\n";

cout<<"\n\nИндивидуальное задание № 2:\n";

cout<<"\nСоставить программу с использованием двумерных динамических\n";

cout<<"\nмассивов для решения задачи индивидуального задания №1.\n";

cout<<"\n\nРабота программы:\n";

cout<<"\nВведите количество строк и столбцов:\n\n"<< "i = " ;

cin >> nrow;

cout<< "j = ";

cin >> ncol;

int **A = new int *;

cout<<"\nВведите элементы массива: \n\n";

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

A[i] = new int;

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

cout << "A[" << i << "][" << j << "] = ";

cin >> A[i][j];

cout<<"\n1) ";

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

bool flag = false;

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

summ += A[i][j];

if(A[i][j] < 0)

if(flag == true)

cout<<"Сумма элементов строки "<< i;

cout<<" с отрицательным элементом"<< " = " << summ << "\n\n";

cout<<"\n2) ";

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

int tempValue; // временная переменная

tempValue = A[i];

// поиск минимального в строке элемента

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

if(A[i][j] < tempValue)

tempValue = A[i][j];

// поиск максимального в столбце элемента

tempValue = A;

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

if(A[j] > tempValue)

tempValue = A[j];

cout<<"Седловая точка: "<< "As[" << max << "][" << min << "]";

2.4. Результаты работы программы:

Лабораторная работа №7. Функции и перегрузка в языке C++

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

Ход работы

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

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

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

Формат простейшего заголовка (прототипа) функции:

тип имя ([список параметров]);

В квадратных скобках записано то, что может быть опущено. Например, заголовок функции main обычно имеет вид:

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

double sin (double);

Здесь записано, что функция имеет имя sin, вычисляет значение синуса типа double, и для этого нужно передать ей аргумент типа double. А вот заголовок функции memcpy, копирующей блок памяти длиной n байтов, начиная с адреса src, по адресу dest:

void *memcpy (void *dest,const void *src,size t n);

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

void *memcpy(void *, const void *. size t);

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

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

Заголовок задает объявление функции. Определение функции, кроме заголовка, включает ее тело, то есть те операторы, которые выполняются при вызове функ­ции, например:

int sum(int a,int b) /* функция находит сумму двух значений */

{ return a + b; // тело функции

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

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

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

double y, x1 = 0.34, x2 = 2;

cout << y << ‘ ‘ << sin (x2) << endl;

y = sin (x1 + 0.5) - sin(x1 - 0.5);

char *cite = “ Never say never ”;

memcpy (b, cite, strlen(cite) + 1);

int summa, a = 2;

summa = sum(a, 4);

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

Пример 7 .1. Передача в функцию параметров стандартных типов

Написать программу вывода таблицы значений функции Ch x (гиперболический ко­синус) для аргумента, изменяющегося в заданных пределах с заданным шагом. Зна­чения функции вычислять с помощью разложения в ряд Тейлора с точностью r.

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

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

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

double cosh(double x, double eps);

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

include

#include

double cosh(double x, double eps); //прототип ф-ции

double Xn, Xk, dX, Eps;

printf(“ | X | Y |\n");

for (double x = Xn; x <= Xk; x += dX)

printf(“|%9.2]f |%14.6g |\n”\ x. cosh(x. eps));

double cosh(double x. double eps)

const int Maxlter - 500; /* максимальное количество итераций */

double ch = 1. у = ch; /* первый член ряда и нач. значение суммы */

for (Int n = 0; fabs(ch) > eps; n++)

ch *- x * x /((2 * n + 1)*(2 * n + 2)); // член ряда

у += ch; // добавление члена ряда к сумме

if (n > Maxlter)

puts(“ Ряд расходится!\n");

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

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

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

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

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

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

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

Листинг 7.1

# include

# include

Double cosh(double x, double eps, int &err);

double Xn, Xk, dX, Eps, y;

printf("Enter Xn, Xk, dX, eps \n");

scanf("%lf%lf%lf%lf.&Xn, &Xk, &dX, &eps);

printf (................................ \n");

printf(“ | X | Y |\n");

printf(.............................\n");

for (double x = Xn; x <= Xk; x += dX)

y = cosh(x, eps, err);

if (err) printf(“|%9.2]|Рядрасходится!|\n”,);

printf(“|%9.2]f |%14.6g |\n”\ x, y);

printf("...............................\n ”);

double cosh(double x, double eps, int err)

const int Maxlter = 500;

double ch - 1. у - ch;

for (int n - 0: fabs(ch) > eps; n++) (ch *- x * x /((2 * n + l)*(2 * n + 2));

if (n > Maxlter);

for(double x=Xn; x<-Xk; x+-dX)

у"cosh(x.eps. err);

if (err) prmtf("|X9.21f|Ряд расходится!|\п и.x);

else printf(M H!9.21f |*14.6g |\n\ x. y);

double cosh(double x. double eps.int &err)

const int Maxlter - 500;

double ch = 1. у = ch;

for (int n = 0: fabs(ch) > eps; n++)

ch *= x * x /((2 * n + l)*(2 * n + 2));

if (n > Maxlter),

Недостатком этого метода является увеличение количества параметров функции. Знак & перед параметром егг - это признак переда­чи параметра по ссылке. Такой способ позволяет передавать значения из функции в вызывающую программу.

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

у = cosh(x + 0.2. eps / 100. err);

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

Ссылка, синтаксически являясь синонимом имени некоторого объекта, в то же время содержит его адрес. Поэтому ссылку, в отличие от указателя, не требуется разадресовывать для получения значения объекта. Если мы передаем в функцию ссылку, то есть пишем в списке параметров выражение вида double Seps, а при вы­зове подставляем на его место аргумент, например eps fact, мы тем самым переда­ем в функцию адрес переменной eps fact. Этот адрес обрабатывается так же, как и остальные параметры: в стеке создается его копия. Функция, работая с копией ад­реса, имеет доступ к ячейке памяти, в которой хранится значение переменной eps fact, и тем самым может его изменить.

Можно передать в функцию и указатель; в этом случае придется применять опера­ции разадресации и взятия адреса явным образом. Для нашей функции примене­ние указателя для передачи третьего параметра будет выглядеть так:

// прототип функции;

double cosh(double х, double eps, int * err);

- // вызов функции;

у = cosh(x, eps, &еrr); // & - взятие адреса

// обращение к еrr внутри функции;

*еrr = 0; // * - разадресация

В прототипе (и, конечно, в определении функции) явным образом ука­зывается, что третьим параметром будет указатель на целое. При вызове на его место передается адрес переменной err. Чтобы внутри функции изменить значе­ние этой переменной, применяется операция получения значения по адресу.

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

Для нашей программы передача вхлдных данных по константной ссылке выглядит так:

// прототип функиии;

double cosh(const double &x. const double &eps. int &err);

- // вызов функции;

у = cosh(x, eps, err); /* обращение к x и eps внутри функции не изменяется */

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

Еще один способ сообщения об ошибках внутри функции - написать функцию так, чтобы параметр ошибки передавался через возвращаемое значение. Это применяется в основном для функций вывода инфор­мации. Например, функция стандартной библиотеки

int fputcdnt ch. FILE *f);

записывает символ ch в поток f. При ошибке она возвращает значение EOF, иначе - записанный символ. В этом случае при необходимости передать в точку вызова * какие-либо другие результаты работы функции их передают через список пара­метров.

Часто в функциях библиотеки в случае возникновения ошибки применяется и более простое решение: при ошибке возвращается значение, равное нулю, хотя ноль может и входить в множество допустимых значений результата. В этом случае у программиста нет средств отличить ошибочное значение от правильного. Напри­мер, таким образом реализованы уже известные вам функции atoi, atol и atof. При невозможности преобразовать строку в число соответствующего типа они возвра­щают ноль, и то же самое значение будет выдано в случае, если в строке содержал­ся символ 0.

Генерация исключения. Воспользуемся средством C++, называемым значениями параметров по умолчанию. Может оказаться неудоб­ным каждый раз при вызове функции cosh задавать требуемую точность вычисле­ния суммы ряда. Конечно, можно определить точность в виде константы внутри функции, задав максимальное допустимое значение, но иногда это может оказать­ся излишним, поэтому желательно сохранить возможность задания точности че­рез параметры. Для этого либо в определении (если оно находится выше по тексту, чем любой вызов функции), либо в прототипе функции после имени параметра указывается его значение по умолчанию, например:

double cosh(double x. double eps - DBL EPSILON);

DBL EPSILON - это константа, определенная в файле . Ее значение равно минимальному числу, которое, будучи при­бавлено к единице, даст не равный единице результат. Теперь нашу функцию можно вызывать с одним параметром, к примеру:

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

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

double cosh(const double x.int & err. const double eps = DBL EPSILON);

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

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

Пример 7 .2. Передача в функцию имени функции

Назовем функцию вывода таблицы значений print tabl. Прежде всего надо опре­делить ее интерфейс. Для того чтобы вывести таблицу, нашей функции потребует­ся знать диапазон и шаг изменения значений аргумента, а также какую, собственно, функцию мы собираемся вычислять. В функцию вычисления суммы ряда надо передавать точность, поэтому точность следует включить в список параметров вызывающей ее функции printtabl. Функция pri nt tabl не возвращает никакого значения, то есть перед ее именем надо указать void.

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

double (*fun)(double, double);

Здесь описывается указатель по имени fun на функцию, получающую два аргу­мента типа doubl e и возвращающую значение того же типа. Часто, если описание типа сложное, с целью улучшения читаемости программы задают для него синоним с помощью ключевого слова typedef:

typedef double (*Pfun)(double, double);

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

void print_tabl(Pfun fun. double Xn, double Xk. double dX. double eps);

Запишем теперь текст программы, сведя к минимуму диагностику ошибок (при превышении максимально допустимого количества итераций функция заверша­ется, возвращая 0, а вызывающая программа выводит это значение):

Листинг 7.2

#include

#include

typedef double (*Pfun)(const double, const double);

void print_tabl(Pfun fun, const double Xn, const double Xk, const double eps);

double cosh(const double x, const double eps);

double Xn, Xk, dX, eps;

prlntf(Enter Xn, Xk, dX, eps \n");

scanf("%lf%lf%lf%lf.” &Xn, &Xk, &dX, &eps);

print tabl(cosh, Xn, Xk, dX, eps);

void print_tabl(Pfun fun, const double Xn, const double Xk, const double dX, const double eps)

pnintf(" ..............................\n");

printf("| X | Y |\n");

printfC ................................ \n");

for (double x = Xn; x < = Xk; x += dX);

printf("|%9.2lf | %14.6g | \n”\,x,fun(x, eps));

printf(" ................................\n);

double cosh(const double x, const double eps)

const int Maxlter = 500;

double ch = 1, у = ch;

for (int n = 0; fabs(ch) > eps; n++)

ch *= x * x /(2 * n + l)/(2 * n * 2);

if (n> Maxlter) return 0;

Функция print tabl предназначена для вывода таблицы значений любой функ­ции, принимающей два аргумента типа double и возвращающей значение того же типа.

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

Пример 7 .3. Передача одномерных массивов в функцию

Даны два массива из n целых чисел каждый. Определить, в каком из них больше по­ложительных элементов.

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

int n posit(const int *a, const int n);

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

Листинг 7.3

#include

int n posit(const int *a, const int n);

cout « "Введите количество элементов:”:cin » n;

int *a = new int[n];

int*b = new int[n];

cout « "Введите элементы первого массива: ";

for (i = 0; i< n; i++) cin » a[i];

cout « "Введите элементы второго массива: ";

for (i = 0; i< n; i++) cin » b[i];

if (n posit(a, n) > n posit(b, n))cout « " В первом положительных больше” « endl;

else if(n posit(a, n) < n_posit(b, n)) cout « " Во втором положительных больше" « endl;

int n posit(const int *a, const int n)

for (int i = 0; i < n; i++)

if (a[i] > 0) count++;

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

int х = {2, 3. -1, -10, 4, -2};

cout « n_posit(x. 10); //будет выведено значение 3

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

int n posit a = n posit(a. n), n posit b = n posit(b, n);

if (n posit a > n posit b) cout « " В первом положительных больше" « endl;

else if (n posit a < n posit b) cout « " Во втором положительных больше" « endl;

else cout « " Одинаковое количество" « endl;

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

Пример 7 .4. Передача строк в функцию

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

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

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

Листинг 7.4

#include

#include

int num num(const char *str);

ifstream fth("test.txt".ios::in|ios::nocreate);

cout « "Нет файла test.txt" « endl;

const int len = 101;

while (fin.getline(str. len))

cout « "В строке “« 1 « " содержится " « num num(str) « " чисел " « endl;

int num num(const char *str)

if (isdigit(*str) && ! isdigit(*(str + 1))) && *(str + 1) != ".") count++;

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

Пример 7 .5. Передача двумерных массивов в функцию

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

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

Листинг 7.5

#include

int ser equals(int **a, const int m, const int n);

if stream fin (."matrix.txt", los:: in | ios:: nocreate);

if (!fin)

cout « "Нет файла matrix.txt" « endl;

int m, n, 1,j;

int **a = new int *[m]; // выделение памяти

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

a[i] = new int [n];

for (i = 0;i < m; i++) // ввод нассива

for (j = 0; j < n) fin » a[i][j];

int line = ser_equals(a, m, n); // вызовфункции

if (line >= 0)cout « " Самая длинная серия в строке " « line;

else cout « " Серий одинаковых элементов нет ";

int ser_equals(int **а, const int m, const int n)

int I,j, count, line = -1, maxcount = 0;

for (1 - 0; 1< m; 1++)

for (j = 0; j < n - 1; j++)

if (a[i][j] == a[l])

if (count > maxcount)

maxcount = count;

if (count > maxcount)

maxcount = count;

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

Если в массиве нет ни одной серии одинаковых элементов, функция вернет значе­ние, равное -1.

Пример 7 .6. Передача структур в функцию

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

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

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

Листинг 7.6

#include

#include

#include //#include

const int l name = 30;

char name;

Man read data();

int append2binfilet (const Man &man, const char* filename);

int print from bin(const char * filename);

char filename = "dbase.bin";

if (append2binfile(read data(), filename) != 0)

puts(" Ошибка при записи в файл ");

puts(" Продолжить (у/n)?”);

if ((y n == "у")||(у n == "Y"))contin = true;

while (contin); print from bin(fi1ename);

int append2binfile(const Man &man, const char* filename)

if ((fout-fopen(filename, "ab"))NULL) return 1;

int success = fwrite(&man, sizeof(man), 1, fout), fclose(fout);

if (success == 1) return 0;

int print from_bin(const char * filename)

int num; Man man; FILE *f;

if ((f = fopenCfilename, "rb")) == NULL) return 1;

fseef((f. 0. SEEKEND);

int n record - ftell(f) / sizeof (man);

puts("Введите номер записи или -1; ");

scanf("&i", &num);

if (num < 0 || num >= n record) break ;

fseek(f. num * sizeof(man). SEEK SET) ;

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

// CharToOem(man,name, man,name);

printf("%30s%5i%10,2f\n, man.name, man.birth year. man.pay);

char name;

puts("Введите фамилию И.О. ");

if (strlen(name) < 1_name)

for (int i = strlen(name); i < l name; i++)

name = 0;

// OemToChar(name. name);

strncpy(man.name. name. l_ name + 1);

puts("Введите год рождения “);

while ((man.birth_year = atoi(buf)) ==0);

puts(“Bвeдитe оклад ");

while (!(man.pay = atof(buf)));

В функции ввода read data предусмотрено заполнение пробелами оставшейся час­ти строковой переменной паше, чтобы формат имени был идентичен формату вво­да в текстовом файле.

Следует обратить внимание на то, как в этой функции выполняется проверка правильно­сти ввода числовой информации. Чтение выполняется в буферную строку, кото­рая затем преобразуется с помощью функций atoi () и atof () в числа. Если функ­ции возвращают 0, преобразование выполнить не удалось (например, вместо цифр были введены буквы), и информация запрашивается повторно. Условие повторе­ния циклов 3 и 4 записано в двух разных вариантах, чтобы вы сами могли оценить, какой из них вам более понятен (профессионалы предпочли бы второй, более ла­коничный вариант).

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

Пример 7 .7. Рекурсивные функции

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

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

Одна из возможных версий программы сортировки приведена ниже.

Листинг 7.7

include

void qsort(float* array, intleft, int right);

const int n = 10;

cout « "введите элементы массива:”;

for (1 = 0; i < n; i++) cin » arr[i];

i = o;r = n - 1; /* левая и правая границы начального фрагмента*/

qsort(arr, 1, r); // 1

for (i = 0; i < n; i++) cout « arr[i] « ‘ ‘;

void qsort(float* array, int left, int right)

int i = left, j = right;

float middle = array[(left + right) / 2];

while (i < j)

while (array[i] < middle) i++;

while (middle < array[j]) j--;

temp = array[i];

array[i] = array[j];

array[j] = temp;

if (left < j) qsort(array, left, j);

if (i < right) qsort(array, I, right);

Процедура разделения реализована здесь в виде рекурсивно вызываемой функции qsort(), в теле которой есть два обраще­ния к самой себе: в операторе 2 - для сортировки левой половинки текущего фраг­мента, и в операторе 3 - для сортировки его правой половинки.

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

Пример 7.8. Многофайловый проект - форматирование текста

Написать программу форматирования текста, читаемого из файла unformt.txt и состоящего из строк ограниченной длины. Слова в строке разделены произвольным количеством пробелов. Программа должна читать входной файл по строкам, фор­матировать каждую строку и выводить результат в выходной файл formatd-.txt. Форматирование заключается в выравнивании границ текста слева и справа пу­тем равномерного распределения пробелов между соседними словами, а также в отступе с левой стороны страницы на margin позиций, то есть результирующий текст должен находиться в позициях margin + 1 .. margin + maxljine. Кроме этого, программа должна подсчитать общее количество слов в тексте.

Алгоритм решения задачи :

    Для каждой строки 11 пе выполнить следующие действия:

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

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

4. После обработки последней строки входного файла вывести на экран значение счетчика слов и закрыть выходной файл.

Разбиение на подзадачи.

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

J void Deflnter (const char* pline, int & base int. int & add int. int & inter)

определяет для строки, на которую указывает pline, количество межсловных промежутков inter, требуемую величину основного интервала base int для каж­дого промежутка (количество пробелов) и величину дополнительного интер­вала add int, определяемую как остаток от деления общего количества пробе­лов в строке на количество межсловных промежутков; последняя величина должна быть равномерно распределена путем добавления одного пробела в каж­дый из первых add i nt промежутков;

void GetLine (FILE* finp. char* pline)

читает очередную строку из входного файла в массив символов с адресом pi ine, ликвидируя при этом пробелы в на­чале строки;

void Putlnterval (FILE* fout. const int k)

выводит очередной интервал, состо­ящий из к пробелов;

int PutWord (FILE*fout,const char*pline.const int startpos)

выводит очеред­ное слово в выходной файл, начиная с позиции startpos текущей строки pi ine; возвращает номер позиции в строке pi i ne, следующей за последним передан­ным символом, или 0 - если достигнут конец строки;

int SearchNextWord"(const char*pline.const int curpos)

возвращает номер пози­ции, с которой начинается следующее слово в строке pi 1 пе, или 0, если достиг­нут конец строки (поиск начинается с позиции curpos).

Разбиение на модули.

Наша программа будет располагаться в двух исходных файлах: task7_7.cpp - с функцией main, edit. cpp - с реализацией перечисленных выше функций, а также заголовочный файл edit.h с интерфейсом этих функций. Ниже приводится содержимое этих файлов.

Листинг 7 .8

// Файл Task7_7.cpp

#include

#include

#include

#include "edit.h"

// Глобальные переменные

const int maxljine = 63;

const int margin = 5;

char line;

int b i, a i, start, next, inter;

printf("Работает программа Task7 7.\n");

if(!(finp = fopen("unformt.txt",”W”)))

printf("Файл unformt.txt не найден.\n”);

printf("Читается файл unformt.txt \n");

if(!(fout = fopen(“formatd.txt", "w")))

printf("Фaйл formatd.txt не создан.\n”);

printf("Выполняется запись в файл formatd.txt.\n");

while(GetLine(finp. line))

DefInter (line, b i, a_i, inter);

PutInterval(fout, margin);

next = PutWord(fout, line, start, nword);

for (int i = 0; i < inter; i++)

start = SearchNextWord(line. next);

Putlnterval(fout.. b i);

if (a j) { a i--; Putlnterval(fout. 1);

next = PutWord(fout. line, start, nword);

if (!next) break;

fprintf(fout. “\n");

printf (“\nКоличество слов - %d\n”, nword);

printf("Работа завершена \n");

///////////////////////////////////////////////////

// Файл Edit.h

// Прототипы функций

void DefInter(const char* pline, Int& base int, int& add int,

int GetLine(FILE*. char*);

void Putlnterval(FILE*. const int);

int PutWord(FILE*. const char*, const int. int&);

int SearchNextWord(const char*, const int);

// Глобальные переменные

extern const int maxl line;

///////////////////////////////////////////////////

// Файл Edit.cpp

#include

#include

#include "edlt.h"

int GetLine(FILE* finp. char* pline)

while ((c = fgetc(finp)) == " ") i++;

if(c == EOF) return 0;

fseek(finp. -1, SEEK CUR);

fgets(pline. Maxl line -i + 1, finp);

pline = 0;

int SearchNextWord(const char* pline, const int curpos)

while(pline[i] !="")

if (pline[i] ==;\n”) return 0:

while (pline[i] == ’ ‘&& pline == " ") i++;

void DefInter(const char* pline. int& base int. int& add int. int& inter)

int к = 0, end;

end = strlen(pline) - 1;

while ((pline == " ") || (pline == ’\n") || (pline == "\r")) end--;

for (unsigned int i= 0; i < end; i++)

if (pline[i] == " ")

if (pline != " ") inter++;

int blank amount * к + maxl line - end;

base int = blank amount / inter;

addjnt = blank amount % inter;

int PutWord (FILE* fout, const char* pline, const int startpos, int& n)

int i = startpos;

while ((c - pline) !=" ‘)

fprintf(fout, "%c", c);

if ((c = "\n"> || (c == "\0"))

void Putlnterval(FILE* fout, const int k)

for (int i=0; i

///////////////////////////////////////////////////

Имена функций мы здесь записали (для разнообразия) в стиле Microsoft, с использованием прописных букв для выделения осмысленных частей имени. Константу maxl 1 пе следует задавать большей, чем максимальная длина строки исходного файла. В качестве самостоятельного упражнения измените про­грамму так, чтобы можно было форматировать текст и в более узкую колонку, чем в исходном файле.

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

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

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

void print(char* str. const int i. const int j)

cout « str « " I" « oct « setw(4) « i « " |" « setw(4) « j « " |’ « endl;

void print(float mas, const int n)

cout « "Массив:" « endl;

cout.setf(ios::fixed);

cout.precision(2);

for (int i = 0; i < n; i++)

cout « mas[i] « " ";

if ((i + 1) % 4 == 0) cout « endl;

void print(Man m)

cout.setf(i os::fixed);

cout.precision(2);

cout « setw(40) « m.name « " ‘ « m.birth year <<" ‘<< m.pay « endl;

В первой из этих функций на экран выводятся строка и два целых числа в восьме­ричной форме, разделенных вертикальными черточками для читаемости. Под каж­дое число отводится по 4 позиции (действие манипулятора setw распространяется только на ближайшее выводимое поле).

Во второй функции для вывода вещественных значений по четыре числа на строке задается вид вывода с фиксированной точкой и точностью в два десятичных знака после запятой. Для этого используются методы установки флагов setf, установки точности precision и константа f1xed, определенная в классе 1os. Точность касается только вещественных чисел, ее действие продолжается до следующей установки.

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

print("После цикла ", 1, п);

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

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

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

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

Пример 7 .9. Перегрузка функций

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

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

Листинг 7.9

#include

#include

#include

#include

const int l name = 30, l year = 5, l pay = 10, l buf = l name + 1 year + l pay;

char name;

int read dbase(const char * filename, Man dbase, const int l dbase, int &n record);

void printtMan m);

void select(Man dbase. const int n record. const int year);

void select(Man dbase. const int n ecord. const float pay);

const int l dbase = 100;

Man dbase;

int n record = 0;

if(read dbase(“txt6.txt”.dbase.1 dbase.n record) !=0) return 1;

cout <<”---------------------“<< endl;

cout << ”1 - Cведения по году рождения“ << endl;

cout <<”2 - Сведения по окладу“<

cout <<”3 - выход“<< endl;

cin >> option;

Case1: << ”Введите год” >> cin >> year;

select(dbase.n_record.year); break;

Case2: << ”Введите оклад” >> cin >> pay;

select(dbase.n_record.pay);

Case 3: return 0;

default: cout << ”Надо вводить число от 1 до 3” << endl;

Void select(man dbase, const int n record, const int year)

Cout << ”Ввод сведений по году рождения” << endl;

bool success = false;

for(int i = 0; i < n record; i++)

if(dbase[i],birth year >= year)

Print(dbase[i]);

if (!success) Cout <<”Таких сотрудников нет”<

Void select(man dbase, const int n_record, const float pay)

cout << ”Ввод сведений по окладу” << endl;

bool success = false;

for(int i = 0; i < n record; i++)

if(dbase[i],birth pay >= pay)

print(dbase[i]);

if (!success) cout <<”Таких сотрудников нет”<

Void print (Man m)

cout.setf(iod::fixed);

cout.precision(2);

cout « setw(40) « m.name « " " « m.birth_year « " " « m.pay « endl;

int read dbase(const char * filename. Man dbase. const int l dbase. int &n record) {

char buf ;

if stream fin(filename. ios::in | ios:mocreate);

cout « "Нет файла " « filename « endl;

while "(fin.getline(buf, 1 buf))

strncpy(dbase[i]name,buf, l name);

dbase[i].name = "\0";

dbase[i].birth year = atoi(&buf);

dbase[i].pay = atof(&buf);

if (i > l dbase)

cout « "Слишком длинный файл";

Правила описания перегруженных функций:

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

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

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

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

Шаблон функции определяется следующим образом:

template тип имя ([список параметров])

/* тело функции */

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

Процесс создания конкретной версии функции называется инстанцированием шаблона или созданием экземпляра функции. Возможны два способа инстанцирования шаблона: а) явный, когда объявляется заголовок функции, в котором все параметризованные типы заменены на конкретные типы, известные в этот момент в программе, б) неявный, когда создание экземпляра функции происходит автома­тически, если встречается фактический вызов функции.

Шаблоны тоже можно перегружать, причем как шаблонами, так и обыч­ными функциями.

Пример 7 .10. Шаблоны функций

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

Поиск максимума - весьма распространенная задача. Для этого достаточно простейшего шабло­на с одним параметром-типом. В саму функцию будет передаваться два аргумента: указатель на массив и длина этого массива.

Листинг 7.10

#include <1ostream.h>

#include

template T Max(T *b. int n);

const int n = 20;

cout « "Введите " « n « " целых чисел:" « endl;

for (i = 0; i < n; i++) cin » b[i];

cout « Max(b, n) « endl;

double a = {0.22, 117.2, -0.08, 0.21, 42.5};

cout « Max(a, 5) « endl;

char *str = "Sophisticated fantastic template";

cout « Max(str. strlen(str)) « endl;

template T Max(T *b, int n)

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

if (b[i] > b) imax = i;

Шаблон функции имеет имя Мах. После ключевого слова tempi ate в угловых скоб­ках перечисляются все параметры шаблона. В данном случае параметр один. При инстанцировании шаблона (в данном случае - неявном), то есть когда компиля­тор будет создавать конкретный вариант функции, этот тип будет заменен конк­ретным стандартным или пользовательским типом. Соответствие устанавливается при вызове функции либо по типу аргументов, либо по явным образом указанно­му типу. Например, последний вызов функции можно записать так:

cout « Max (str, strlen(str));

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

Аналогично обычным параметрам функции, можно задавать значение параметра шаблона по умолчанию.

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

Аппаратура и материалы. Для выполнения лабораторной работы необходим персональный компьютер со следующими характеристиками: процессор Intel Pentium-совместимый с тактовой частотой 800 МГц и выше, оперативная память - не менее 64 Мбайт, свободное дисковое пространство - не менее 500 Мбайт, устройство для чтения компакт-дисков, монитор типа Super VGA (число цветов от 256) с диагональю не менее 15. Программное обеспечение - операционная система Windows2000/XP и выше, среда разработки приложений Microsoft Visual Studio.

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

Методика и порядок выполнения работы. Перед выполнением лабораторной работы каждый студент получает индивидуальное задание. Защита лабораторной работы происходит только после его выполнения (индивидуального задания). При защите лабораторной работы студент отвечает на контрольные вопросы, приведенные в конце, и поясняет выполненное индивидуальное задание. Ход защиты лабораторной работы контролируется преподавателем.Порядок выполнения работы:

1. Проработать примеры, приведенные в лабораторной работе.

2. Выполнить задания согласно варианта индивидуального задания №1 лабораторной работы №6, оформив каждый пункт задания в виде функ­ции. Все необходимые данные для функций должны передаваться им в качестве параметров. Использование глобальных переменных в функциях не допускается.

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

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

Вариант:


    Напишите программу вычисления функции Аккермана для всех неотрицательных целых аргументов т и п:

    а и b

    Для заданных границ интегрирования а и b вычислите значение определенного интеграла следующего вида:


п = 0,1,2, … . За ответ принять приближение, для которого выполняется условие
, где = 0,0001.

    Для заданных границ интегрирования а и b вычислите значение определенного интеграла следующего вида:

    Для заданных границ интегрирования а и b вычислите значение определенного интеграла следующего вида:

    Для заданных границ интегрирования а и b вычислите значение определенного интеграла следующего вида:

    Для заданных границ интегрирования а и b вычислите значение определенного интеграла следующего вида:

    Для заданных границ интегрирования а и b вычислите значение определенного интеграла следующего вида:

    Для заданных границ интегрирования а и b вычислите значение определенного интеграла следующего вида:

    Для заданных границ интегрирования а и b вычислите значение определенного интеграла следующего вида:

    Для заданных границ интегрирования а и b вычислите значение определенного интеграла следующего вида:

    Для заданных границ интегрирования а и b вычислите значение определенного интеграла следующего вида:

    Для заданных границ интегрирования а и b вычислите значение определенного интеграла следующего вида:

    Для заданных границ интегрирования а и b вычислите значение определенного интеграла следующего вида:

    Для заданных границ интегрирования а и b вычислите значение определенного интеграла следующего вида:

1. Названия лабораторной работы.

3. Ответов на контрольные вопросы лабораторной работы.

4. Формулировки индивидуальных заданий и порядка их выполнения.

Отчет о выполнении лабораторной работы в письменном виде сдается преподавателю.

Вопросы для защиты работы

1. Что представляет собой функция в С++? Что нужно для ее использования?

2. Приведите пример заголовка функции.

3. Что включает в себя определение функции?

4. В чем отличие функции от других программных объектов?

5. Каким образом происходит вызов функции?

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

7. Каков механизм передачи параметров в функцию?

8. Способы передачи входных данных.

9. Что представляет собой средство C++, называемое значениями параметров по умолчанию?

10. Каким образом происходит передача в функцию имени функции?

11. Каким образом происходит передача одномерных массивов в функцию?

12. Каким образом происходит передача строк в функцию?

13. Каким образом происходит передача двумерных массивов в функцию?

14. Каким образом происходит передача структур в функцию?

15. Какая функция называется рекурсивной? Преимущества и недостатки рекурсии.

16. Что называется перегрузкой функций? Перечислите правила описания перегруженных функций.

17. Область применения шаблонов.

18. Что такое инстанцирование? Способы инстанцирования шаблона.

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

Назначение

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

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

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

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

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

Организация

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

Сложное программное обеспечение при сборке требует использования десятков или даже сотен файлов с исходным кодом. В таких случаях для упрощения сборки обычно используются файлы проектов, содержащие описание зависимостей между файлами с исходным кодом и описывающие процесс сборки. Эти файлы также могут содержать параметры для компилятора и среды проектирования. Для разных сред проектирования могут применяться разные файлы проекта, причём в некоторых средах эти файлы могут быть в текстовом формате, пригодном для непосредственного редактирования программистом с помощью универсальных текстовых редакторов, в других средах поддерживаются специальные форматы, а создание и изменения файлов производится с помощью специальных инструментальных программ. Файлы проектов обычно включают в понятие «исходный код». Часто под исходным кодом подразумевают и файлы ресурсов, содержащие различные данные, например графические изображения, нужные для сборки программы.

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

Качество

В отличие от человека, для компьютера нет «хорошо написанного» или «плохо написанного» кода. Но то, как написан код, может сильно влиять на процесс сопровождения ПО . О качестве исходного кода можно судить по следующим параметрам:

  • читаемость кода (в том числе наличие комментариев к коду);
  • лёгкость в поддержке, тестировании, отладке и устранении ошибок, модификации и портировании;
  • экономное использование ресурсов: памяти, процессора, дискового пространства;
  • отсутствие замечаний, выводимых компилятором;
  • отсутствие «мусора» - неиспользуемых переменных, недостижимых блоков кода, ненужных устаревших комментариев и т. д.;
  • адекватная обработка ошибок;
  • возможность интернационализации интерфейса.

Неисполняемый исходный код

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

В таких случаях исходным кодом считается форма данной работы, предпочтительная для её редактирования. В лицензиях, предназначенных не только для ПО, она также может называться версией в «прозрачном формате». Это может быть, например:

  • для файла, сжатого с потерей данных - версия без потерь;
  • для рендера векторного изображения или трёхмерной модели - соответственно, векторная версия и модель;
  • для изображения текста - такой же текст в

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

Что такое листинг

Понятие листинг встречается в разных сферах нашей жизни:

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

Две последние отрасли мы рассматривать не будем. Нас интересует листинг на , а также криптовалютных.

Листинг и делистинг ценных бумаг

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

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

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

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

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

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

Этапы листинга

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

  1. Начинается все с подачи заявления. Сделать это может как сам эмитент, так и лицо, представляющее интересы компании.
  2. Далее наступает стадия экспертиз. Представители биржи анализируют как ценные бумаги, так и все доступные данные о компании. Исследуется рентабельность предприятия, ликвидность его активов. Компания обязана предоставить всю финансовую отчетность, собранную за последние несколько лет.
  3. Специальная комиссия рассматривает результаты экспертиз и решает добавлять ценные бумаги в свой листинг или отклонить заявку.
  4. Если решение положительное, обе стороны – компания и биржа, заключают соглашение.

Процедура, в среднем, занимает около 1-2 месяцев. Чтобы оставаться в списке, эмитенту потребуется, как правило, один раз в квартал, подавать нужные данные бирже.

Правила листинга, предъявляемые торговыми площадками к компаниям, разнятся. Одни могут допускать к листингу только предприятия, капитализация которых составляет не менее 50 миллионов долларов, а время присутствия на рынке – от 3 лет. Другие могут как повышать, так и понижать планку этих и других требований.

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

Уровни листинга

Преимущественно на биржах представлено несколько уровней листинга. В первый премиальный попадают наиболее ликвидные бумаги с высоким уровнем надежности.

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

К примеру, на действует Основная и Альтернативная площадки. Первая делится на два уровня: «Стандарт» и «Премиум». Альтернативный рынок предназначен для мелких и средних развивающихся предприятий, которые допускаются сюда по упрощенной процедуре.

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

Виды листинга

Различают первичный и вторичный листинг.

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

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

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

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

В чем преимущества эмитента

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

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

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

Что это дает инвесторам

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

Что такое делистинг

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

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

Листинг криптовалют

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

Криптовалютные проекты стремятся попасть в листинги популярных бирж

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

Цена вопроса

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

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

В начале года журналисты Business Insider опубликовали статью, согласно которой минимальный порог для вхождения в листинг криптобирж для ICO-проектов составляет 50 тысяч долларов, а в отдельных случаях может достигать и 1 миллиона долларов.

Также были случаи, когда руководство бирж попадалось на взятках за включение монет в листинг. В качестве примера можно привести биржу Coinnest – ее операционному и техническому директорам заплатили около 890 тысяч долларов за добавление в торговый список криптовалюты S-coin.

Как это работает

Чтобы токен попал в листинг, чаще всего на выбранной площадке необходимо подать заявку и заполнить анкету. Однако, популярные монеты биржи могут включать в листинг и самостоятельно, не дожидаясь пока команда проекта предложит сделать это. К примеру, на каждой бирже в обязательном порядке присутствует биткоин (BTC), и как правило, Ethereum (ETH).

Какие вопросы чаще всего встречаются в анкете:

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

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

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

Важные нюансы

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

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

Монеты, которые могут быть признаны ценными бумагами, биржи стараются не добавлять . Например, Poloniex сразу предлагает разработчикам ознакомиться с тестом Хоуи, чтобы определиться может токен подпасть под эти критерии или нет.

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

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

«Эффект бирж»

После добавления в листинги популярных криптобирж, стоимость монет, как правило резко вырастает – в среднем на 25-30%. Эта закономерность даже получила название «эффект бирж». Происходит это благодаря тому, что о монете узнает большее количество пользователей, она стает узнаваемой, повышает на нее спрос. Однако чаще всего этот взлет кратковременный и вскоре стоимость начинает снижаться.

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

Делистинг криптомонет производят по ряду причин:

  • низкий интерес со стороны трейдеров;
  • изменения в законодательстве;
  • взлом блокчейна криптосети;
  • отказ разработчиков от дальнейшей поддержки монеты;
  • жалобы пользователей.

Удаляются токены, как правило, не сразу – биржа дает несколько недель трейдерам на закрытие позиций и вывод средств на собственные кошельки.

Листинг в торговле

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

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



Есть вопросы?

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: