Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
исправленный курсовик 2012 заоч.doc
Скачиваний:
12
Добавлен:
15.03.2015
Размер:
5.05 Mб
Скачать

3 . Указания к выполнению курсовой работы

3.1 Анализ задачи.

В соответствии с поставленной задачей требуется разработать программу на языке программирования C++ , которая выполняет следующие операции:

  • Осуществляет чтение из текстового файла содержимое титульного листа вашей курсовой работы.

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

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

  • Организует хранение отсчетов времени, входного и выходного сигналов в трех отдельных файлах.

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

3.2 Разработка структуры проекта.

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

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

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

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

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

3.3 Реализация проекта.

  • Создание и сохранение проекта в среде IDE NetBeans в соответствии в разработанной структурой проекта.

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

  • Написание программного кода всех функций.

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

3.4 Оформление пояснительной записки

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

Замечания

До начала работы над программой необходимо :

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

Приведение входного сигнала и/или передаточной характеристики цепи,

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

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

  • В математической системе Maxima произвести контрольный расчет в N равноотстоящих точках заданного диапазона t [Tнач –Tкон] значений входного и выходного сигналов в соответствии с вашим конкретным заданием. Эти графики в дальнейшем можно будет сравнить с графиками, построенными вами в соответствии со значениями, полученными программным путем. Именно поэтому в программе должна присутствовать функция, которая позволяет сохранить значения массива времени, массивов входного и выходного сигналов в файлах. Совпадение этих графиков подтвердит правильность работы вашей программы.

  • Cоздать текстовый файл, в котором будет находиться описание титульного листа вашей курсовой работы. Этому файлу можно, например, дать имя “TitleList.txt”, или любое другое имя по вашему усмотрению.

Пример выполнения расчетов и построения графиков в математической

системе Maxima приведен на стр

Работа в системе Maxima будет дополнительно изучена в лаборатории кафедры в сессию.

Общие рекомендации

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

  • Тип переменных программист выбирает самостоятельно. При этом он должен учитывать и диапазон изменения переменных и требуемую точность представления данных.

  • Имена переменным выбирает также сам программист. Желательно давать эти имена осмысленно, исходя из их назначения.

  • Не забывайте об интерфейсных подсказках. Это корректно по отношению к пользователям. Они не должны сидеть перед пустым экраном.

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

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

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

Приложение П

Теоретический материал

Нам предстоит работать:

  • с массивами входного и выходного сигналов и с массивом времени;

  • с функциями, реализующими отдельные функционально законченные части нашей программы;

  • с функциямиж

  • инструментом, позволяющим выполнить курсовую работу предлагается использовать среду программирования IDE NetBeans и язык программирования С++;

  • для проведения контрольных расчетов рекомендуется использовать математическую систему Maxima.

П 1. Массивы

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

Описание одномерных массивов

тип имя [размерность]

int x[5] //описание массива с именем x из 5 целых чисел

Размерность массива указывается в квадратных скобках []. Эта размерность вместе с типом его элементов определяет объем памяти, который необходим для его размещения:

количество байтов = <размерность базового типа> * <количество элементов>

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

Основные свойства одномерных массивов

  • Признак массива при описании – наличие парных квадратных скобок []. Константа или константное выражение в [ ] задает число элементов массива.

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

  • все элементы располагаются в памяти друг за другом; массив занимает непрерывную область памяти.

  • индекс первого элемента равен 0, поэтому максимальный индекс для элементов массива всегда на единицу меньше размерности массива.

  • имя массива является указателем - константой, равной адресу начала массива (первого байта первого элемента массива);

доступ к элементам массива осуществляется по имени массива и индексу

элемента.

Замечания

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

В Си существует два способа доступа к переменным:

  • ссылка на переменную по имени:

int a;

a=5;

  • использование механизма указателей:

int a;

int *pa; // указатель на переменную целого типа

pa=&a; // в указатель записывается адрес а

*pa=15; // по адресу, записанному в указатель pa ,будет записано значение 15

pa a

&a ---15 , где pa – указатель, ссылающийся на а (говорят, что pa указывает на а, или pa ссылается на а).

Так как унарный оператор & выдает адрес объекта, то можно написать pa=&a. Еще раз напоминаем, что оператор & применяется только к объектам, расположенным в памяти: к переменным и элементам массивов.

Указатели могут быть:

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

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

Признаком указателя – переменной для компилятора является наличие в описании переменной двух компонентов:

тип объекта данных, для доступа к которому используется указатель;

символ * перед именем переменной.

В совокупности тип и * воспринимаются компилятором как особый тип данных – “указатель на что-либо”.

Итак, указатель может быть константой или переменной, а также он может указывать на константу или переменную:

int x; //целая переменная

const int n=3; // целая константа

int *px; //указатель на целую переменную

const int * pn; //указатель на целую константу

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

В пару к унарному оператору &- взятия адреса имеется унарный оператор * - раскрытие ссылки. (обращение к содержимому по адресу, равному значению указателя):

*p1=*p2+4; // взять содержимое памяти по адресу, равному значению указателя p2, прибавить к этому содержимому 4, а результат поместить по адресу, равному значению указателя p1.

Инициализация указателей

Осуществляется с помощью присваивание указателю адреса существующего объекта:

int x;

int * px=&x; // использование операции &

char arr[10];

char * parr=arr; //с помощью имени массива, так как имя массива в этом случае само является адресом начала массива).

arr==&arr[0], где arr[0] –первый элемент массива (элемент массива с индексом =0).

Альтернативные способы задания элементов массива

pa=&a[0]--------|a[0] | a[1]| a[2] |a[3] |a[4]|

a a+1 a+2 a+3 a+4

&a[0] &a[1] &a[2] &a[3] &a[4]

pa pa+1 pa+2 pa+3 pa+4

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

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

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

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

Замечание. Мы узнали, что имя массива и адрес его первого элемента

эквивалентны. Имя массива в действительности является указателем. Поэтому мы не можем присвоить ему новое значение. Имена массивов не являются адресуемыми значениями, и оператор вида имя массива = выражение недопустим, так как нельзя изменить адрес массива.

Выводы по массивам

  • Массив- это структура данных, представляющая набор переменных одинакового типа, имеющих общее имя.

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

  • Нумерация элементов массива начинается с нуля, поэтому максимальный индекс для элементов массива на единицу меньше размерности массива.

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

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

  • Ввод / вывод элементов массива и его обработка выполняются только в цикле.

  • Работая с массивом в цикле обратите внимание на то, что параметр цикла и индекс массива всегда имеют одно и то же имя. Это принципиально важно.

  • Указатель – это переменная, в которой хранится адрес области памяти.

  • При работе с массивами автоматически формируется указатель с именем массива. Имя массива является указателем на его начальный элемент (значение указателя равно адресу нулевого элемента массива).

  • Доступ к элементам массива можно осуществить через указатель с именем массива. Так как указатель является константой, то его можно использовать в выражениях, но нельзя изменять.

П2. ФУНКЦИИ

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

ФУНКЦИЯ – это логически самостоятельная именованная часть программы, которой можно передать параметры, и которая может возвратить значение.

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

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

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

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

  • объявить (задекларировать) функцию;

  • определить (описать) функцию;

  • вызвать функцию.

Объявление (декларация) функции

Задает имя функции, тип возвращаемого этой функцией значения и список передаваемых параметров:

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

Если тип не указан, предполагается по умолчанию, что функция возвращает целое типа int.

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

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

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

(int x, int y, float z)

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

Определение (описание) функции (стандарт ANSI)

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

{

тело функции

}

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

  • Тип возвращаемого значения может быть любым, кроме массива и функции (но может быть указателем на массив и функцию);

  • Список формальных параметров - определяет величины, передаваемые в функцию (типы, имена). Если в функцию ничего не передается, то поле списка аргументов либо пусто ( ) , либо (void). Элементы списка разделяются запятыми;

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

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

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

имя_ функции([список фактических параметров]);

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

Обмен информацией между функциями

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

  • с помощью глобальных переменных;

  • через возвращаемое значение;

  • с помощью передачи параметров.

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

Возвращаемое значение реализуется оператором return.

Оператор return имеет два варианта использования:

  • вызывает немедленный выход из текущей функции и возврат в вызывающую программу;

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

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

Передача параметров

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

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

Существует два способа передачи параметров в функции:

  • по значению: в стек заносятся копии значений аргументов, и операторы функции работают с этими копиями;

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

нет и возможности их изменения;

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

.

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

Передача массивов в качестве параметров

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

int function(int arr[], const int n);

int function(int *arr, const int n);

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

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

Замечание

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

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

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

Выводы по функциям

1.Функция – это логически самостоятельная именованная часть программы. Использование функций упрощает структуру программы.

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

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

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

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

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

7. Массивы всегда передаются в функцию по адресу. Количество элементов в массиве должно передаваться отдельным параметром.

8. В многофайловом проекте надо уметь разбить задачу на подзадачи и распределить функции по файлам. По сути файлы соответствуют отдельным модулям. Но в С++ нет конструкций для обозначения модулей, но есть понятие – единица трансляции. Единица трансляции представляет отдельный файл с исходным текстом на С++, который получается после обработки препроцессором. Такое разбиение на отдельные файлы требует последующей сборки. Так как в С++ отсутствуют конструкции для обозначения модулей, то нет и конструкций для их сборки в исполняемую программу. Эта задача решается средствами интегрированной среды, в которой создается проект. В составе проекта перечисляются все объектные модули. Процесс сборки полной программы из объектных модулей называется компоновкой. Программа компоновки входит в состав системы программирования. При компоновке в программу собираются и разрабатываемые пользователем модули (файлы) , и стандартные модули из стандартных объектных библиотек. Разделение программы на модули требует согласования определений и объявлений в разных единицах трансляции.

П3. Работа с файлами

В заголовочном файле <stdio.h> расположены прототипы функций для работы с файлами. Здесь же определена специальная структура типа FILE. Поля этой структуры содержат системную информацию о файле. Пользователь может не знать подробности строения и использования системой этой структуры, но он должен описать переменную типа FILE и уметь использовать ее при вызове функций, работающих с файлами.

char *filename=”f1.txt”; //имя файла

FILE *f2; // указатель на структуру типа FILE

if((f2=fopen(filename ,"r"))==NULL){

printf("can't open your file\n");

exit(1);

Функция fopen пытается найти и открыть файл с именем “f1.txt” и связать поток ввода- вывода с указателем f2. Параметр “r” определяет режим доступа. В данном конкретном случае он открывает существующий файл только для чтения. Если указатель f2 получает значение NULL,то это означает, что файл открыть не удалось, попытка оказалась неудачной. Для исправления положения делаем выход exit(1) и разбираемся c ситуацией.

П4. Создание многофайлового проекта.

Создание нового проекта в интегрированной среде IDE NetBeans

Integrated development Environment( интегрированная среда разработки) – это программный продукт, который может объединять текстовый редактор, компилятор, отладчик, компоновщик. Вам предстоит работать со средой IDE NetBeans.v . Курсовую работу будем оформлять в виде отдельного проекта.

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

После запуска NetBeans вы увидите перед собой экран с верхней полоской меню (Рис.П.1).

Рис. П. 1

Вызываем пункт меню File/New Project. В появившемся окне New Project выбираем Categories C/C++(подсветка слева).

Справа щелчком подсвечиваем пункт C/C++Application, переходим к следующей операции щелчком Next (Рис. П. 2).

Рис. П. 2

Далее предлагается выбрать имя проекта и его местоположение(Project Name and Location). Имя, которое вы дадите проекту, получит и папка, в которой этот проект будет храниться.

В окошечке Set as Main project не забудьте поставить птичку. И нажмите Finish(Рис. П. 3).

Рис. П. 3

Слева в окне с названием Projects появится значок с именем вашего проекта. Щелкнув по этому значку, вы увидите из каких файлов состоит ваш проект:

Header files

Resource Files

Source Files

Important Files.

Выделите Sourse Files цветом , войдите в меню File/New File и выберите С++Files и Main C++Files, нажмите кнопку Next (Рис. П. 4).

Рис. П .4

Теперь определитесь с именем файла, расширением(cpp) и папкой, в которой будете хранить файл, и нажмите кнопку Finish (Рис. П. 5).

Рис. П. 5

Пример выполнения проекта

Возьмем пример и выполним его в виде проекта.

Постановка задачи.

Ввести с клавиатуры два целочисленных массива ‘а’ и ‘в’ и их размерности. Количество элементов в массивах не должно превышать 10. В каждом массиве вычислить произведение элементов, кратных 3. Первые элементы в каждом массиве заменить на полученное произведение. Ввод элементов массивов a и b ,обработку массивов и вывод результатов оформить в виде функций. Окончательно задача должна быть выполнена в виде проекта.

В разделе исходных файлов (sourse files) будут находиться два файла с расширением .cpp. Это главный файл c именем “main.cpp”, в котором будет храниться определение функции с именем main и другой файл c именем “func.cpp”, в котором будут храниться определения всех остальных функций с именами input,change и output.

В разделе Header Files разместим заголовочный файл с именем ” func.h”. В этом собственном заголовочном файле разместим прототипы наших функций.

Заголовочный файл с именем “func.h” будет выглядеть так :

Заголовочный файл “func.h

#ifndef_FUNC_H // “страж определен?” if !defined

// _FUNC_H , если не определен, то

// его надо определить

#define_FUNC_H //определение стража

int input(int a[],const int n);

int change(int a[],const int n); // прототипы функций

int output(int a[],const int n);

#endif/*_FUNC_H*/ // конец #ifndef

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

В разделе Sourse Files разместим файл с именем “func.cpp”. В этом файле разместим определения наших функций input(),change() и output() (все функции, кроме main()).

Файл “func.cpp выглядит так:

#include<stdio.h>

#include”func.h”

int input(int a[],const int n) {

int i;

printf("input array:\n");

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

printf("a[%d]=",i);

scanf("%d",&a[i]);

}

printf("\n");

return 0;

}

int change(int a[],const int n){

int i,pr=1;

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

if(a[i]%3==0)

pr*=a[i];

a[0]=pr;

}

int output(int a[],const int n) {

int i;

for(i=0;i<n;i++) printf("a[%d]=%d\n",i,a[i]);

}

Наконец, файл с именем “main.cpp” будет содержать определение функции main.

Файл “main.cpp”

#include<stdio.h>

#include”func.h”

int main() {

int a[N],b[N],n1,n2;

printf("input razmer a=");

scanf("%d",&n1);

printf("input razmer b=");

scanf("%d",&n2);

input(a,n1);

change(a,n1);

output(a,n1);

input(b,n2);

change(b,n2);

output(b,n2);

return 0;

}

}

Обратите внимание, мы, подключая с помощью директивы #include свой пользовательский заголовочный файл (не стандартный) используем кавычки, а не привычные уголки(“func.h”).

В окне Projects, щелкнув по значку с именем вашего проекта и раскрыв значки Header Files и Sourse Files вы увидите как разместились ваши файлы в этих разделах:

Header Files

func.h

Sourse files

main.cpp

func.cpp

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

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

П.5.1. Исходные данные:

Входной сигнал, заданный аналитически, и рабочий набор исходных данных:

Uвх(t)=U1*cos(2*3.14*t/T)+U2*cos(3*3.14*t/T) //Входной сигнал

T=2c U1=15в г2=8в; 0<=t<=T // Рабочий набор исходных данных для этого входного сигнала

Передаточная характеристика цепи задана в виде графика uout(uin):

U4

Рис.П.5.1. Графическое задание передаточной характеристики

Рабочий набор исходных данных для передаточной характеристики:

U1=32в U2=60в U3=12в U4=20в

Найти: Момент времени, в который выходной сигнал достигает уровня, равного 0,7 Umax.

П.5.2. Приведение передаточной характеристики к аналитическому виду

Из графика видно, что uout(uin) имеет три линейных участка. Только один из них (между U3 и U4 ) нуждается в переводе к аналитическому виду:

a1*U3+b1=U1

a1*U4+b1=U2

Отсюда:

b1=U1-a1*U3

Тогда:

a1*U4+U1-a1*U3=U2

a1=(U2-U1)/(U4-U3)

Окончательно:

uout=((U2-U1)/(U4-U3))*uin+U1-a1*U3

a=(U2-U1)/(U4-U3)

b=U1-a1*U3

Подставляя исходный набор рабочих данных окончательно получаем:

a=3.5

b=-10

Uвых(t)= 32 if uin(t)<=12

3.5*uin(t)-10 if uin(t)<=20

60 if uin(t)>20

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

Работа с системой компьютерной алгебры Maxima.

Для нас важно, что Maxima способна работать с системами Windows, Linux, MacOS X. Сама система Maxima написана на языке Common Lisp. Система производит численные расчеты с достаточно высокой точностью, строит графики функций.

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

Ввод в систему исходных значений в соответствии с нашим заданием выглядит в системе Maxima следующим образом:

(%i1) U1:15;

U2 : 8;

T : 2;

tn : 0;

tk : T;

uin(t):=U1*cos(2*3.14*t/T)+U2*cos(3*3/14*t/T);

wxplot2d( [ uin( t )] , [ t , 0 , 2] ,

[ gnuplot_preamble,”set grid ; ”] );

(%o1) 15

(%o2) 8

(%o3) 2

(%o4) 0

(%o5) 2

(%o6) uin ( t ) := U1 cos (2 3.14 t / T) + U2 cos (3 3.14 t / T)

На рис показан график входного сигнала, построенный системой Maxima в соответствии с введенными исходными данными.

Рис .П.5.3.1. График входного сигнала

(%o7)

(%o8) uout (t):=if uin(t)>=20 then 60 else if uin(t) >=12 then 3.5*uin(t) -10 else 32;

wxplot2d([uout(t)],[t,0,2],

[gnuplot_preamble,”set grid;”])$

(%8) uout(t):=if uin(t)>=20 then 60 else if uin(t)>=12 then 3.5 uin(t)-10 else 32

Рис.П.5.3.2. График выходного сигнала

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

П .5.4 Разработка проекта, реализующего курсовую работу.

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

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

Таким образом, в наш проект входят три файла – “main.cpp”, “func.cpp” и “func.h”.

Определения всех наших функций собраны в файле “func.cpp”. Главная функция –main находится в файле “main.cpp” и отвечает за алгоритм работы всей программы. От нее зависит последовательность вызовов всех остальных функций программы. Прототипы собственных наших функций хранятся в файле

“ func.h”.

.

KURSOVIK – (имя проекта)

“func.h” “func.cpp” “ main.cpp” (имена файлов)

Файл для zastavka() определяет

хранения menu() алгоритм

прототипов uin1() работы

собственных uout1() всей программы

функций table()

formingW()

writeinfo()

Файл “func.h” содержит прототипы всех используемых в программе функций.

Файл “func.cpp” содержит определения всех наших функций.

Файл “main.cpp” реализует алгоритм решения поставленной задачи

П5.5. Назначение функций программы

Функция zastavka работает с текстовым файлом “TitleList.txt”. Функция считывает и выводит на экран титульный лист вашей курсовой работы.

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

Функция uin1 реализует алгоритм формирования массивов отсчетов времени и отсчетов входного сигнала в соответствующие моменты времени.

Прототип функции имеет вид:

int uin1(int n, float uin[], float tarr[], float U1, float U2, float T, float tn, float tk);

Выходными параметрами в списке формальных параметров являются :

  • float tarr[] –массив временных отсчетов для входного и выходного сигналов.

  • float uin[] - массив отсчетов входного сигнала в моменты времени, соответствующие массиву временных отсчетов.

Все остальные параметры в списке формальных параметров являются входными:

  • n –число отсчетов для всех трех массивов (задаете самостоятельно)

  • U1, T ,U2 ,tn, tk; (аналитический вид входного сигнала и набор исходных данных для входного сигнала смотри в постановке задачи).

Входные параметры мы передаем через список формальных параметров внутрь функции, потому что без них не могут быть рассчитаны наши выходные параметры, то есть те параметры , ради которых и создается эта функция. Передача конкретных значений произойдет при вызове этой функции. (Конкретные значения этих параметров смотри в рабочем наборе исходных данных для входного сигнала : T=2c,U1=15в, U2=8в,tn=0, tk=T.)

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

Функция uout формирует массив отсчетов выходного сигнала.

Входными параметрами для этой функции являются массив отсчетов входного сигнала, вычисленного функцией uin1, и количество отсчетов (параметр n).

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

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

Функция formingW вычисляет заданный параметр W для выходного сигнала.

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

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

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

Функция writeinfo осуществляет запись в файл нужных вам значений массивов.

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

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

П5.6Таблица описания пользовательских функций.

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

Прототип функции Входные и Назначение параметров

выходные

параметры

______________________________________________________________

int writeinfo Все параметры - n- количество сохраняя-

(int n,char fname[],float mas[]) входные емых точек

fname[] –имя файла для

сохранения

mas[] –имя сохраняемого

массива

В вашей курсовой работе такая таблица должна содержать описания прототипов всех ваших функций.

П.5.7.Текст программы

Файл “main.cpp

#include <stdlib.h>

#include<stdio.h>

#include<math.h>

#include"func.h"

int main(){

char ch;

float tarr[1000],uin[1000],uout[1000],W; //Выделение памяти под исходные

float U1=15,U2 =8,tn=0,T=2,tk=T; // данные и под результаты работы

int n;

zastavka();

printf("\ninput n=");

scanf("%d",&n);

uin1(n,uin,tarr,U1,U2,T,tn,tk);

uout1(n,uin,uout);

menu();

do {

printf("input your cod:");

scanf("%c",&ch);

switch(ch) {

case '1' : table(n,tarr,uin,uout); break;

case '2' : {

writeinfo(n,"f1.txt",uin);

printf("f1.txt saved\n\n");

writeinfo(n,"f2.txt",uout);

printf("f2.txt saved\n\n");

writeinfo(n,"f3.txt",tarr);

printf("f3.txt saved\n\n");

}

break;

case '3' : {

float e=0.01; //заданная точность

float v=10000; // предыдущее значение параметра W

int n=50; //количество точек

float p=1.0;

float ud;

do {

uin1(n,uin,tarr,U1,U2,T,tn,tk);

uout1(n,uin,uout);

float del=(tk-tn)/(n-1);

ud=formingW(n,uout,del); // текущее значение параметра W

p=fabs(v-ud)/ud; // текущее значение точности вычисления W

n=2*n; //ение количества точек

v=ud; // текущее значение W становится предыдущим

}while(p>e);

printf("\n\n");

printf("tochnost uout dostignuta\n");

printf("iskomaja dlitelnost ud=%lf\n",ud);

printf("tochnost p=%f\n",p);

printf("kolich tochek n=%d\n",n/2);

printf("zadan tochnost e=%f\n\n",e);

}

break;

case '4' :printf("finish,put<enter>,please:");

exit(1);

}

}

while(ch!='4');

return 0;

}

File : ‘func.cpp”

#include<stdio.h>

#include<math.h>

#include"func.h"

int zastavka() {

FILE *f2; // указатель на структуру типа FILE

char ch;

if((f2=fopen("titleList.txt","r"))==NULL){

printf("can't open your file\n");

exit(1);

}

ch=getc(f2); // чтение символа

while(ch!=EOF) // End Of File –конец файла

{

putchar(ch); //вывод символа на экран

ch=getc(f2);

}

fclose(f2);

return 0;

}

==================================

int menu() {

printf(" MAIN MENU\n\n");

printf(" 1 - Table\n");

printf(" 2 - Save\n");

printf(" 3 - Show W\n");

printf(" 4 - Exit\n ");

return 0;

}

===========================

int uin1(int n, float uin[],float tarr[],float U1,float U2,float T,float tn,float tk){

int i;

float del=(tk-tn)/(n-1);

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

tarr[i]=tn+i*del;

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

uin[i]=U1*cos(2*3.14*tarr[i]/T)+U2*cos(3*3.14*tarr[i]/T);

return 0;

}

===================

int uout1(int n,float uin[],float uout[]) {

int i;

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

if(uin[i]>=20)

uout[i]=60;

else

if(uin[i]>=12)

uout[i]=3.5*uin[i]-10;

else

uout[i]=32;

return 0;

}

========================

int table(int n,float tarr[],float uin[],float uout[]) {

int i;

printf("\n TABLE ");

printf("\n| i | time | uin | uout |");

printf("\n__________________________________________________");

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

printf("\n| %6d |%12.9f | %15.8f | %20.8f |",i+1,tarr[i],uin[i],uout[i]);

return 0;

}

========================

float formingW(int n,float uout[],float del) {

int i,kol=0;

float w,max;

max=uout[0];

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

if(uout[i]>max)

max=uout[i];

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

if(uout[i]>0.7*max)

kol++;

w=del*(kol-1);

return w; //возвращение значения параметра W в точку вызова функции

}

=======================

int writeinfo(int n,char fname[],float mas[]) {

int i;

FILE *f;

f=fopen(fname,"w");

if(f==NULL)

printf("\n error");

else

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

fprintf(f,"%13.5f\n",mas[i]);

fclose(f);

return 0;

}

File: “ func.h”

#ifndef _FUNC_H //страж включения (если он не определен,

#define _FUNC_H // то его надо определить.)

int zastavka();

int menu();

int uin1(int n, float uin[],float tarr[],float U1,float U2,float T,float tn,float tk);

int uout1(int n,float uin[],float uout[]);

int table(int n,float tarr[],float uin[],float uout[]);

float formingW(int n,float uout[],float del);

int writeinfo(int n,char fname[],float mas[]);

#endif /*_FUNC_H */

// конец программы

В этом примере использовался форматированный ввод/вывод информации в стиле С, то есть мы работали с функциями scanf() и printf() и подключали заголовочный файл <stdio.h>, хранящий прототипы этих функций.

При желании вы можете использовать потоковый ввод/вывод в стиле С++, то есть работать с объектами cin и cout, используя заголовочный файл <iostream.h>.

Тогда операция ввода с клавиатуры >>, а операция вывода на экран << .

Замечание:

-при использовании стандартной библиотеки С++(ISO/IEC 14882) заголовочные файлы указываются без расширения .h, но используется директива using namespace std; (использование стандартного пространства имен), так как все имена в стандартной версии библиотек принадлежат пространству std. В случае использования более старой версии заголовочный файл пишется с расширением h, а using namespace std не используется.

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

П.5.8. Работа в системе Maxima с целью проверки полученных программным путем результатов.

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

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

Рис.П.5.8.1. Построение таблицы значений

массивов времени, входного и выходного сигналов

На рис П5.8.2 представлены результаты работы программы при вызове пункта меню 3.(Show W). Результаты показывают, что заданная точность выходного сигнала при расчете параметра W достигнута. Приведены значение искомой длительности то есть момент времени, когда значение выходного сигнала достигает величины 0.7 от максимального значения (t=0,230576). Показано, что для этого понадобилось 400 точек. Полученная при этом точность вычисления p=0,002513 при заданной точности вычислений 0,01.

В верхней части экрана на рисунке виден ответ программы на выбор пункта меню 2, где мы просили сохранить в файлах f1.txt,f2.txt? f3.txt полученные значения массивов. Программа вывела на экран сообщение о том, что эти значения в указанных файлах сохранены.

Рис. П.5.8.2.Результаты вычисления параметра W с

заданной точностью

Рис.П.5.8.3 График входного сигнала, построенный в

соответствии со значениями, полученными в программе.

Рис.П.5.8.4. График выходного сигнала, полученный в соответствии с данными программы

Рис П.5.8.3 и рис П.5.8.4 возвращает нас из системы NetBeans в систему Maxima. На экране видно как мы считываем содержимое файлов f1.txt, f2.txt и f3.txt в три отдельных списка с помощью оператора read_list. Эти три файла содержат значения отсчетов массивов времени, входного и выходного сигналов. По этим значениям просим систему Maxima построить дискретные графики входного и выходного сигналов соответственно. Видно, что графики совпадают с нашим контрольным расчетом. Это подтверждает правильность разработанной нами программы. На этом работу над проектом можно считать полностью законченной.

Хотим напомнить вам слова Конфуция:

“Что я слышу, я забываю.

Что я вижу, я запоминаю.

Что я делаю, я знаю

Конфуций.

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

Желаем успехов! Всегда готовы помочь!

Уважаемые студенты! В случае возникновения вопросов по курсовой работе вы можете обратиться по адресу электронной почты или по телефону, которые указаны на сайте кафедры ЦВТиИ (цифровая вычислительная техника и информатика) к ответственному за работу с заочным факультетом.

Список литературы

  1. Современные методы программирования на языках С и С++:

учебное пособие/ Л.Б. Бузюков, О.Б. Петрова. – СПб:Линк,2008.- 290с.

2. Программирование на языке высокого уровня C/C++: учебное пособие/И.О. Воронцова, Л.А. Груздева, Т.В. Губанова. – СПб:Теледом,2010 -110с

3. Полный справочник по С++/ Г. Шилдт. –СПб: ИД”Вильямс”,2008

61