Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Фролов Отчет.doc
Скачиваний:
7
Добавлен:
05.03.2016
Размер:
901.63 Кб
Скачать

34

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

ГОСУДАРСТВЕННОЕ ВЫСШЕЕ УЧЕБНОЕ ЗАВЕДЕНИЕ

ПРИАЗОВСЬКИЙ ГОСУДАРСТВЕННЫЙ ТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ

Факультет Информационных технологий

Кафедра Информатики

Курсовая работа

по дисциплине “Программирование”

Выполнил:

студент группы ВТ-11

Фролов Д.В.

Проверил:

кандидат техн. наук, доцент

Бурса А. Г.

Мариуполь - 2012

Индивидуальное задание на курсовую работу.

Вариант 12

Задание 1: Написать функцию, которая в произвольном ряде X определяет количество вхождений ряда Y.

Задание 2: Создать структуру данных о работниках в фирме: фамилия, имя, отчество, адрес (улица, дом, квартира) и дата поступления на работу (месяц, год). Во вторую структуру записать данные только тех, кто на сегодняшний день проработал не меньше 5 лет. Сохранить результат в файл.

Задание 3: Превратить массив Х, расположив его элементы в обратном порядке.

Задание 4: Получить число 1! + 2! + .. + 100!, выводя его по одной цифре. Программу реализовать в виде функции.

Реферат

Пояснительная записка к курсовой работе: 31 страница, 4 приложения, 11 рисунков.

В качестве языка написания программного обеспечения предполагается использовать СИ, а в качестве среды программирования – Visual C++ 2010 с использованием стандартных компонентов.

Данный отчет по курсовой работе содержит:

  • содержание, которое называет разделы, и номера страниц, где расположены данные разделы;

  • реферат, в котором содержится перечень ссылок, описание отчета, структура отчета.

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

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

  • реферат с поставленных теоретических вопросов включает в себя, подробные ответы на два теоретических вопроса;

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

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

  • приложения, в которые входят распечатки программ, иллюстрации и т. д.

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

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

Содержание

ВВЕДЕНИЕ……………………………………………………………………………………5

1 РЕФЕРАТЫ ПО ПОСТАВЛЕННЫМ ТЕОРЕТИЧЕСКИМ ВОПРОСАМ……………...6

1.2 Теоретическое задание 1…………………………………………………………...6

1.2 Теоретическое задание 2…………………………………………………………..11

2 ОПИСАНИЕ РЕШЕНИЯ ПОСТАВЛЕННЫХ РАСЧЕТНЫХ ЗАДАЧ……...………….15

2.1 Описание решения к задаче 1………………………………………………….….15

2.2 Описание решения к задаче 2………………………………………………….….16

2.3 Описание решения к задаче 3………………………………………………….….18

2.4 Описание решения к задаче 4………………………………………………….….19

ВЫВОДЫ……………………………………..……………………………………………….20 СПИСОК ИСПОЛЬЗОВАНЫХ ИНФОРМАЦИОННЫХ ИСТОЧНИКОВ……………….21

ПРИЛОЖЕНИЕ……………………………...……………………………………………..…22

Приложение 1…………………………………………………………………………22

Приложение 2………………………………………………………………………….24

Приложение 3………………………………………………………………………….27

Приложение 4………………………………………………………………………….29

Введение

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

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

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

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

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

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

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

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

1 РЕФЕРАТЫ ПО ПОСТАВЛЕННЫМ ТЕОРЕТИЧЕСКИМ ВОПРОСАМ

1.1 Теоретическое задание 12

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

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

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

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

Персональные компьютеры IBM используют машинный язык микропроцессоров семейства 8086, т.к. их аппаратная часть основывается именно на данных микропроцессорах.

Можно писать программы непосредственно на машинном языке, хотя это и сложно. На заре компьютеризации(в начале 1950-х г.г.), машинный язык был единственным языком, большего человек к тому времени не придумал. Для спасения программистов от сурового машинного языка программирования, были созданы языки высокого уровня (т.е. немашинные языки), которые стали своеобразным связующим мостом между человеком и машинным языком компьютера. Языки высокого уровня работают через трансляционные программы, которые вводят "исходный код" (гибрид английских слов и математических выражений, который считывает машина), и в конечном итоге заставляет компьютер выполнять соответствующие команды, которые даются на машинном языке. Существует два основных вида трансляторов: интерпретаторы, которые сканируют и проверяют исходный код в один шаг, и компиляторы, которые сканируют исходный код для производства текста программы на машинном языке, которая затем выполняется отдельно.

При классификации языков выделяют следующие типы языков:

Ассемблерные языки — являются символьным представлением машинных языков конкретного компьютера.

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

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

Декларативные языки — языки, оперирующие инструкциями данным и отношениями между ними. Алгоритм скрывается семантикой языка. Это аппликативные языки, языки логики и объектно-ориентированные языки. Примеры декларативных свойств - сложные множества и инструкции поиска по шаблону.

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

Аппликативные языки — функции применяются к значениям без побочного эффекта. Это Функциональные языки во всем своем многообразии.

Функциональные языки — оперируют функциями высокого порядка. В них манипуляции совершаются напрямую функциями, а не данными. К категории функциональных языков относятся Lisp, FP, APL, Nial, Krc.

Объектно-ориентированные языки — языки, в которых данные и функции, имеющие доступ к ним рассматриваютс как один модуль. Пример: Object Pascal, С++, Java, Objective Caml.

Языки запросов — обеспечивают интерфейс к базам данных.

Языки четвертого поколения (4GL) — высокоуровневые языки, могут использовать естественный английский язык или визуальные конструкции. Алгоритмы или структуры данных обычно выбираются компилятором.

Языки логики — языки, оперирующие предикатами и их отношениями p(x, Y). Программы состоят из набора заключений Хорна, которые могут быть:

фактами - p(X,Y) есть истина;

правилами - p истинно, если q1, q2 и qn истинны;

запросами - верны ли q1, g2 и gn? Где gi - цель.

 Машинно – ориентированные языки – это языки, наборы операторов и изобразительные средства которых существенно зависят от особенностей ЭВМ (внутреннего языка, структуры памяти и т.д.). Машинно –ориентированные языки позволяют использовать все возможности и особенности Машинно – зависимых языков:

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

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

- предсказуемость объектного кода и заказов памяти;

- для составления эффективных программ необходимо знать систему команд и особенности функционирования данной ЭВМ;

- трудоемкость процесса составления программ ( особенно на машинных языках и ЯСК), плохо защищенного от появления ошибок;

- низкая скорость программирования;

- невозможность непосредственного использования программ, составленных на этих языках, на ЭВМ других типов.

Машинно-ориентированные языки по степени автоматического программирования подразделяются на классы.

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

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

Есть также языки, включающие в себя все возможности ЯСК, посредством расширенного введения макрокоманд - они называются Автокоды.

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

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

Обе указанных системы используют трансляторы с ЯСК и набор макрокоманд, которые также являются операторами автокода.

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

. Макрос

Язык, являющийся средством для замены последовательности символов описывающих выполнение требуемых действий ЭВМ на более сжатую форму - называется Макрос (средство замены).

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

Макрос одинаково может работать, как с программами, так и с данными.

Машинно – независимые языки

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

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

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

Проблемно – ориентированные языки

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

Проблемных языков очень много, например:

Фортран, Алгол – языки, созданные для решения математических задач;

Simula, Слэнг - для моделирования;

Лисп, Снобол – для работы со списочными структурами.

Об этих языках я расскажу дальше.

Универсальные языки

Универсальные языки были созданы для широкого круга задач: коммерческих, научных, моделирования и т.д. Первый универсальный язык был разработан фирмой IBM, ставший в последовательности языков Пл/1. Второй по мощности универсальный язык называется Алгол-68. Он позволяет работать с символами, разрядами, числами с фиксированной и плавающей запятой. Пл/1 имеет развитую систему операторов для управления форматами, для работы с полями переменной длины, с данными организованными в сложные структуры, и для эффективного использования каналов связи. Язык учитывает включенные во многие машины возможности прерывания и имеет соответствующие операторы. Предусмотрена возможность параллельного выполнение участков программ.

Программы в Пл/1 компилируются с помощью автоматических процедур. Язык использует многие свойства Фортрана, Алгола, Кобола. Однако он допускает не только динамическое, но и управляемое и статистическое распределения памяти.

Диалоговые языки

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

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

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

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

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

Непроцедурные языки

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

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

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

Функциональные языки программирования. Программа на таком языке представляет  собой совокупность описаний функций и выражения, которые необходимо вычислить. Оно вычисляется посредством редукции (т. е. серии упрощений). Функциональное программирование не использует концепцию памяти как хранилища значений переменных. Операторы присваивания отсутствуют, вследствие чего переменные обозначают не области памяти, а объекта программы, что полностью соответствует понятию переменной в математике. Наличие стройной математической основы обеспечивает возможность использования алгебраических методов создания структуры, преобразования и исследования программ. Это в какой-то мере приближает их к описанию структуры мышления человека. Примером функционального языка является язык LISP (List Processing-обработка списков) Разработан и реализован в Массачусетском технологическом институте в 1959 г. Рассматривается специалистами как основной язык программирования систем искусственного интеллекта.

Логическое программирование Логика и программирование долгое время были непересекающимися областями исследований. Только в 1973 впервые было опубликовано описание языка PROLOG (PROgramming in LOGic- программирование в терминах логики) Центральным понятием в логическом программировании является отношение. Программа представляет собой совокупность определений отношений между объектами и цели. В логическом программировании нужно только специфицировать факты, на которых алгоритм основывается, а не определять последовательность шагов, которые требуется выполнить. Логические программы отличаются принципиально низким быстродействием. Так как вычисления осуществляются методом проб и ошибок (посредством поиска с возвратами). В настоящее время для ПК существует около двух десятков реализации PROLOG’а, некоторые из которых оформлены в виде интегрированных сред.

Объектно-ориентированное программирование. Корни объектно - ориентирования уходят в одну из ветвей логики, в которой первичной является не отношение, а объект. Прототипом объектно-ориентированного программирования явился язык SIMULA-67. Но оформилось оно в самостоятельный стиль программ ирония с появлением языка (SMALLTALK-1972 г.), первоначально предназначенного для реализаций функций машинной графики. Этот стиль программирования характеризуется богатыми графическими возможностями и средой программирования, развитой модульной структурой программ. Именно модульность упрощает разработку сложных программных продуктов. Как пример объектно-ориентированного языка можно назвать Visual Basic  и Delfi.

1.2 Теоретическое задание 32

Указатель - некоторое символическое представление адреса. В языке Си имеются и переменные типа указатель. Точно так же как значением переменной типа char является символ, а значением переменной типа int - целое число, значением переменной типа указатель служит адрес некоторой величины.  Возможны только две операции с функциями: вызов и взятие адреса. Указатель, полученный с помощью последней операции, можно впоследствии использовать для вызова функции. Например:

 void error(char* p) { /* ... */ }          void (*efct)(char*);   // указатель на функцию          void f()          {            efct = &error;       // efct настроен на функцию error            (*efct)("error");    // вызов error через указатель efct          }

Для вызова функции с помощью указателя (efct в нашем примере) надо вначале применить операцию косвенности к указателю - *efct. Поскольку приоритет операции вызова () выше, чем приоритет косвенности *, нельзя писать просто *efct("error"). Это будет означать *(efct("error")), что является ошибкой. По той же причине скобки нужны и при описании указателя на функцию. Однако, писать просто efct("error") можно, т.к. транслятор понимает, что efct является указателем на функцию, и создает команды, делающие вызов нужной функции.

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

          void (*pf)(char*);          // указатель на void(char*)           void f1(char*);             // void(char*);           int f2(char*);              // int(char*);           void f3(int*);              // void(int*);           void f()           {             pf = &f1;                 // нормально             pf = &f2;                 // ошибка: не тот тип возвращаемого                                       // значения             pf = &f3;                 // ошибка: не тот тип параметра             (*pf)("asdf");            // нормально             (*pf)(1);                 // ошибка: не тот тип параметра             int i = (*pf)("qwer");    // ошибка: void присваивается int           }

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

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

  typedef int (*SIG_TYP)(int);    // из <signal.h>   typedef void (SIG_ARG_TYP)(int);   SIG_TYP signal(int, SIG_ARG_TYP);

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

         typedef void (*PF)();          PF edit_ops[] = { // команды редактора              &cut, &paste, &snarf, &search          };          PF file_ops[] = { // управление файлом             &open, &reshape, &close, &write          };

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

Выбор происходит нажатием клавиши мыши:

         PF* button2 = edit_ops;          PF* button3 = file_ops;

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

Если  пользователь выбрал позицию меню, которая определяется, например, как позиция 3 для клавиши 2, то соответствующая команда реализуется вызовом:

          (*button2[3])();

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

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

           typedef int (*CFT)(void*,void*);            void sort(void* base, unsigned n, unsigned int sz, CFT cmp)            /*               Сортировка вектора "base" из n элементов               в возрастающем порядке;               используется функция сравнения, на которую указывает cmp.               Размер элементов равен "sz".               Алгоритм очень неэффективный: сортировка пузырьковым методом             */             {               for (int i=0; i<n-1; i++)                   for (int j=n-1; i<j; j--) {                      char* pj = (char*)base+j*sz;  // b[j]                      char* pj1 = pj - sz;          // b[j-1]                      if ((*cmp)(pj,pj1) < 0) {                      // поменять местами b[j] и b[j-1]                         for (int k = 0; k<sz; k++) {                             char temp = pj[k];                             pj[k] = pj1[k];                             pj1[k] = temp;                         }                       }                     }              }

В подпрограмме sort неизвестен тип сортируемых объектов; известно только их число (размер массива), размер каждого элемента и функция, которая может сравнивать объекты. Мы выбрали для функции sort() такой же заголовок, как у qsort() - стандартной функции сортировки из библиотеки С. Эту функцию используют настоящие программы.

Покажем, как с помощью sort() можно отсортировать таблицу с такой структурой:

            struct user {                char* name;     // имя                char* id;       // пароль                int dept;       // отдел             };             typedef user* Puser;             user heads[] = {                  "Ritchie D.M.",      "dmr",   11271,                  "Sethi R.",          "ravi",  11272,                  "SZYmanski T.G.",    "tgs",   11273,                  "Schryer N.L.",      "nls",   11274,                  "Schryer N.L.",      "nls",   11275                  "Kernighan B.W.",    "bwk",   11276             };             void print_id(Puser v, int n)             {               for (int i=0; i<n; i++)                   cout << v[i].name << '\t'                        << v[i].id << '\t'                        << v[i].dept << '\n';             }

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

            int cmp1(const void* p, const void* q)             // сравнение строк, содержащих имена             {               return strcmp(Puser(p)->name, Puser(q)->name);             }             int cmp2(const void* p, const void* q)             // сравнение номеров разделов             {               return Puser(p)->dept - Puser(q)->dept;             }

Следующая программа сортирует и печатает результат:

           int main()            {              sort(heads,6,sizeof(user), cmp1);              print_id(heads,6);    // в алфавитном порядке              cout << "\n";              sort(heads,6,sizeof(user),cmp2);              print_id(heads,6);    // по номерам отделов            }

Допустима операция взятия адреса и для функции-подстановки, и для перегруженной функции ($$R.13.3).Отметим, что неявное преобразование указателя на что-то в указатель типа void* не выполняется для параметра функции, вызываемой через указатель на нее. Поэтому функцию

         int cmp3(const mytype*, const mytype*);

Нельзя использовать в качестве параметра для sort(). Поступив иначе, мы нарушаем заданное в описании условие, что cmp3() должна вызываться с параметрами типа mytype*. Если вы специально хотите нарушить это условие, то должны использовать явное преобразование типа.

2 ОПИСАНИЕ РЕШЕНИЯ ПОСТАВЛЕННЫХ РАСЧЕТНЫХ ЗАДАЧ

2.1 Описание решения к задаче 1

Описание предметной области:

Написать функцию, которая в произвольном ряде X определяет количество вхождений ряда Y.

Информационная модель.

Исходные данные: массив str1 и str2,типа char, res типа int лдя хранения результата

Промежуточные данные: массив tmp,типа char.

Выходные данные: тип int.

Математическая модель:

В данной задаче я использую массив tmp для записи кусочка строки в этот массив. Который в свою очередь проверяется со массивом str2, как только он совпадает переменная res увеличивается на 1, тем самым говоря что мы нашли подстроку в этой строке.

Описание программы:

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

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

Контрольный пример:

Рисунок 1 – Контрольный пример к задаче 1

Листинг программы и алгоритм в виде блок-схемы к данной задаче представлен в приложении 1.