Тема 1. Первая программа на С. — КиберПедия 

Двойное оплодотворение у цветковых растений: Оплодотворение - это процесс слияния мужской и женской половых клеток с образованием зиготы...

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

Тема 1. Первая программа на С.

2019-12-26 125
Тема 1. Первая программа на С. 0.00 из 5.00 0 оценок
Заказать работу

Тема 1. Первая программа на С.

История языка программирования С.

История языка С начинается с операционной системы UNIX, которая была написана на С. Общая среда разработки UNIX/C создала языку С репутацию языка системного программирования, так как он удобен для написания компиляторов и операционных систем. Но С оказался удобным и для написания важнейших программ в самых различных областях.

Первоначально UNIX была разработана в 1969 году на компьютере DEC PDP-7 в лаборатории фирмы Bell. Вскоре Кен Томпсон создал компилятор нового языка, названного В. После этого появился новый компьютер, названный PDP-11 (отечественный аналог —
СМ-3). Это был довольно слабый по теперешним меркам компьютер (24 Кб оперативной памяти и 512 Кб памяти на жестком магнитном диске). Попытка написания операционной системы UNIX для этого компьютера на языке В не увенчалась успехом, т.к. этот язык ориентировался на слова, а PDP-11 — на байты. Кроме того, он был языком интерпретирующего типа, что существенно замедляло выполнение программ. В результате в 1971 году была начата работа по созданию языка С.

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

Достоинства языка С:

малый набор синтаксических правил,

богатый набор библиотечных функций,

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

слабая типизация (свободное манипулирование данными),

структурированность,

поддержка модульного программирования,

простой интерфейс с ассемблерными программами,

эффективность использования памяти,

переносимость.

Недостатки языка С:

слабая типизация (необходим контроль со стороны программиста),

отсутствие проверок на этапе исполнения.

 

Структура программы.

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

Текстовый файл начинается с команд препроцессора
#include <имя файла заголовков.h>. Далее следует описание функций, текст которых находится в другом файле или в этом же файле, но в конце файла. Описание глобальных переменных предшествует тексту функций. В любом месте программы можно вставлять комментарии, которые начинаются двумя знаками деления (//) и идут до конца строки. В одном из файлов должна существовать функция с именем main – для DOS приложения, или WinMain – для Windows приложения. Эта функция является точкой входа в программу и с нее начинается сборка.

Пример простейшей программы:

//

// Это первая наша программа

// Автор – Я, 2004

//———————————-

#include <stdio.h>

int main()

{

printf(“Это пример простейшей программы.”);

return 0;

}

 

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

Строка #include <stdio.h> подключает файл заголовков стандартной библиотеки ввода-вывода.

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

Первым оператором функции main является вызов функции printf, которая вызывается для вывода на экран текста, заключенного в кавычки. Каждый оператор в языке С заканчивается точкой с запятой.

Оператор return используется для завершения функции и возврата целого числа «нуль».

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

Представление данных.

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

Целые числа записываются как последовательность цифр. Впереди числа может стоять его знак (плюс или минус), в конце - символ L(эль) для представления числа двойной длины. Числа с плавающей запятой записываются в виде +1.234e-56 (знак числа, целая часть, точка, дробная часть, символ e, знак порядка, порядок). Эта запись соответствует числу 1,234*10-56. Можно опускать различные части представления, важно только, чтобы число не выглядело как целое (1..12 1e-5 – это примеры чисел 1, 0,12, 0,00001). Текстовые строки записываются в двойных кавычках, одиночные символы в одинарных кавычках.

Чтобы выделить память для данных конкретного типа необходимо определить переменную. Переменные, используемые в программе, должны быть объявлены. Объявление начинается с указания типа переменной, за которым пишутся имена переменных, разделенные запятыми. Именами переменных может быть любой набор букв латинского алфавита, цифр и знака _ (подчеркивание). Первой должна быть буква. Заглавные и строчные буквы различаются. Каждая переменная должна быть инициализирована. Это можно сделать непосредственно в описании, например целые переменные a_9, x7a и Alpha описываются следующим образом:

int a_9, x7a=3, Alpha = 0; a_9=-27345;

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

Многократно используемую константу можно описать так же, как и переменную, добавив слово const перед описанием, например:

const int buffersize=128;

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

В языке имеются следующие типы данных:

char – отдельный текстовый символ, обычно он занимает один байт,

int – целое число, обычно занимает 2 байта,

long (int) – целое число двойной длины, обычно занимает 4 байта,

float – числа с плавающей точкой обычной точности, занимают 4 байта,

double – числа с плавающей точкой двойной точности, занимают 8 байт,

long double – числа с плавающей точкой двойной точности, занимают 10 байт,

void - величина нулевой длины и не имеющая значения.

Дополнительно может использоваться модификатор типа unsigned, который позволяет объявлять некоторые типы переменных как беззнаковые.

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

Спецификаторы auto и register указывают на локальное время жизни переменной, а спецификаторы static и extern – на глобальное. Объект с глобальным временем жизни существует на протяжении всего времени выполнения программы.

Если переменная объявлена на внешнем уровне (допустимы классы памяти static или extern), то она видима во всей оставшейся части файла. Класс extern указывает на то, что переменная описана или в другом файле или в этом же файле, но позже.

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

Операции.

В языке С имеется большой набор операций, Стандартный набор включает операции сложения +, вычитания -, умножения *, деления /, остатка от деления %. Дополнительно имеются операции увеличения на 1 (автоинкремента)++, автодекремента --, поразрядного сдвига вправо >> и влево <<. Кроме этого, имеются поразрядные логические операции И &, ИЛИ | и НЕ!.

Присваивание в языке С выполняет операция, а не оператор. Результат присваивания – это число, которое тоже можно присваивать, например:

x=5+(y=2);

Дополнительно в язык включены составные операции присваивания вида (операция)= позволяющие сжато записывать выражения, например r*=5+x; означает r=r*(5+x).

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

Особенности компьютерных вычислений налагают дополнительные требования к выражениям. Необходимо следить за переполнением чисел, а также за возможностью их обнуления. Например, выражение “x*2” может дать неожиданный отрицательный результат, если x - это целое число, большее, чем 32767/2, а “x/(x+1)” дает ноль.

Следует иметь ввиду, что в выражениях выполняется автоматическое преобразование типов данных, если это необходимо (в смешанных операциях). Преобразования выполняются в соответствии с иерархией типов (int -> long -> float ->double) и порядком вычислений. Пример: x=y+i/j; Вначале выполняется операция деления. Если i и j – целые, то выполняется их целочисленное деление, результат которого преобразуется в плавающий формат и складывается с y.

Математические функции.  

В арифметических выражениях можно использовать большой набор математических функций. Они определены в заголовочном файле <math.h>. Функция вызывается путем указания ее имени, за которым в круглых скобках следует список аргументов, например

y=2*M_PI/asin(-0.5);

// M_PI-константа, определенная в math.h,

// asin - функция arcsin.

Практическое задание №1.

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

Для операций консольного ввода‑вывода используются функции библиотеки stdio.h (printf и scanf), для вычисления математических функций — библиотека math.h (функции fabs, exp, log, sin, cos и т.д.).

 

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

            

Ветвящиеся алгоритмы.

Описанные условные операторы позволяю создавать достаточно сложные программы. Рассмотрим для примера программу решения линейного уравнения ax+b=0.

//

// Решение линейного уравнения ax+b=0

// (C) Демонстрационная программа

// 1999 год.

#include <stdio.h>

int main()

{

double a,b,x;

printf(“enter a:”);

scanf(“%lf”,&a);

printf(“enter b:”);

scanf(“%lf”,&b);

if(a==0)

{

       if(b==0)

             printf(“every x is solution.”);

       else

             printf(“no solution.”);

}else

{

       x=-b/a;

       printf(“x=%lf”,x);

}

return 0;

}

Тема 3. Функции.

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

Определение функции.

В общем случае функция имеет следующий формат:

<возвращаемый тип> ИмяФункции (параметры)
{

//Здесь следует тело функции,

//состоящее из операторов
}

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

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

Обратите внимание, что знак «точка с запятой» не ставится после списка параметров.

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

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

<возвращаемый тип> ИмяФункции (параметры);

В конце списка параметров стоит знак «точка с запятой», это и указывает на то, что мы имеем дело не с описанием функции, а с ее прототипом.

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

Доступ к элементам массива.

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

for (int idx=0;idx<7;idx++)

s+=Temperatura[idx];

Нумерация элементов массива начинается с нуля. Т.е. индекс массива определяет смещение используемого элемента относительно начала массива.

Передача массивов функциям.

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

int function(double a[],int size);

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

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

x=function(myarray,50);

Функция получает доступ ко всем элементам массива и может их изменять. Для запрета изменения можно добавить модификатор const:

int function(const double a[],int size);

Указатели.

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

тип_указываемых данных *имя_указателя;

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

int i=100;// определяется целая переменная

int *point_i;// определяется указатель на целую переменную

pointi=&i;// указатель инициализируется адресом переменной i

printf(“%i”,*pointi); // выводится значение переменной,

// определяемое указателем. Оно равно значению переменной i (100).

Обратите внимание на операцию определения адреса (&). Она является противоположной разыменованию.

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

int array[10];

int *iptr=array;

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

Указатель можно индексировать как массив. Следующие два оператора эквивалентны:

array[3]=10;

*(array+3)=10;

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

int *ptemp=array;

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

*(ptemp++)=0;

можно использовать для обнуления массива array.               

Потоковые функции.

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

Когда программа открывает файл для ввода вывода при помощи потоковых функций, то открытый файл связывается с некоторой переменной типа FILE (определенной в stdio.h), содержащей базовую информацию об этом файле. После открытия потока с помощью функции fopen возвращается указатель на эту переменную. Этот указатель используется для ссылки к файлу при всех последующих операциях ввода-вывода и называется указателем потока.

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

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

Для использования потоковых функций в программу должен быть включен заголовочный файл stdio.h. В нем содержатся описания прототипов функций ввода/вывода, а также - описания ряда констант. Константа EOF определяется как значение, возвращаемое при обнаружении конца файла, BUFSIZE - размер буферов потока, тип FILE определяет структуру, используемую для получения информации о потоке.

Поток открывается с помощью функций fopen(), fdopen() или freopen(). В момент открытия задаются режим файла и способ доступа. Эти функции возвращают указатель на переменную типа FILE, например

FILE *file1;

file1=fopen(“input.dat”,”r”);

открывает файл input.dat для чтения. Переменная file1 получает указатель на поток.

Возможные типы доступа:

“a” – запись в режиме добавления в конец файла,

”a+” –тоже, что и “a”, но возможно и чтение,

”r” – только для чтения,

”r+” – для чтения и записи,

”w” – открывается пустой файл для записи,

”w+” – открывается пустой файл для записи и чтения.

Когда начинается выполнение приложения, автоматически открывается следующие потоки: стандартное устройство ввода stdin, стандартное устройство вывода stdout, устройство сообщений об ошибках stderr, устройство печати stdprn и стандартное дополнительное устройство stdaux. Эти файловые указатели можно использовать во всех функциях ввода/вывода в качестве указателя на поток. Некоторые функции автоматически используют указатели на поток, например getchar() и putchar() используют stdin и stdout соответственно.

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

Для перемещения по файлу можно использовать функции fseek(), ftell() и rewind().

Потоки cin, cout, cerr.

В языке С++ имеется другая библиотека ввода/вывода, определяемая заголовочным файлом iostream.h. Ввод/вывод в ней определяется набором специальных классов. Аналогами потоков stdin, stdout и stderr являются cin, cout и cerr. Они открываются автоматически при запуске программы.

Операции выделения >> и вставки <<.

Для ввода/вывода с помощью указанных потоков используются специальным образом определенные операции “занести в поток” и “получить из потока”, << и <<. Операция >> выделяет данные из входного потока и помещает в указанные переменные, а операция << помещает значения указанных переменных в поток.

Приведем пример использования потока stdin и потока cin:

scanf(“%d%lf%c”,&ivalue,&dvalue,&cvalue);

cin>>ivalue>>dvalue>>cvalue;

Аналогично для вывода:

printf(“Integer:%d double: %lf”,ivalue,dvalue);

cout<<”Integer:”<<ivalue<<” double:”<<dvalue;

Практическое задание №4.

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

Для работы с файлами и прочими процедурами ввода-вывода используйте функции библиотеки stdio.h (fopen, fclose, (f)printf, (f)scanf, feof), для динамического распределения памяти - операторы new и delete, для операций со строками - функции библиотеки STRING (strcpy, strcat, strlen, strcmp).

Вариант 1.

Дан текстовый файл. Определите длину файла, количество строк в файле и количество пробелов в файле. Имя файла введите с консоли.

Вариант 2.

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

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



Вариант 3.

Напишите программу обработки статистических данных. Определите:

а) объем статистической выборки             .

б) среднее арифметическое выборки     

в) дисперсию 

г) среднеквадратичное отклонение       

Имя файла введите с консоли.

Файл состоит из строк, которые содержат одно действительное число в каждой строке. Число строк, а следовательно и количество чисел в файле, заранее неизвестно.

Вариант 4.

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

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

                        

                                    

                            

Вариант 5.

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

Вариант 6.

Дан файл, содержащий записи, состоящие из двух полей - числового и текстового (подробно структуру файла см. приложение 5). Упорядочите записи в порядке возрастания числового поля. Упорядоченный список запишите в файл. Имена входного и выходного файлов вводите с консоли.

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

 

Вариант 7.

Вычислите  методом треугольника Паскаля.

,              .

Полученные вектора  запишите в файл построчно. Имя файла и количество строк n вводите с консоли.

Вариант 8.

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

Файл состоит из строк. Каждая строка содержит единственное слово. Число строк в файле заранее не известно.

Синтаксис структур.

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

Структура создается при помощи ключевого слова struct, за которым следует поле тега (имя структуры) и список элементов. Описание структуры заканчивается точкой с запятой, т.к. оно является оператором:

struct поле_тега

{

тип_элемента1 имя_элемента1;

тип_элемента2 имя_элемента2;

тип_элемента3 имя_элемента3;

};

Пример описания структуры:

struct stboat

{

char type[16]; // тип

char model[16]; // модель

char title[20]; // имя

int year;    // год выпуска

double price; // цена

};

Эта структура описывает новый тип данных stboat и содержит три текстовых поля, одно целое и одно действительное.

С описанной структурой не связывается никакая переменная. Для создания новой переменной используется оператор (слово struct является необязательным):

struct имя_структуры имя-переменной;

Для вышеприведенного примера можно создать переменную used_boat:

struct sboat used_boat;

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

struct

{

char type[16]; // тип

char model[16]; // модель

char title[20]; // имя

int year;    // год выпуска

double price; // цена

} used_boat;

Структуры и битовые поля.

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

struct поле_тега

{

тип_элемента1

имя_поля1:колич_бит1,

       имя_поля2:колич_бит2,

       имя_поля3:колич_бит3,

       …;

тип_элемента2

       …

};

В таких структурах можно использовать только целочисленные типы:

struct keybits

{

unsigned char

       shift:1,

       ctrl:1,

       scrool:1,

       lock:1;

};

Объединения.

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

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

union поле_тега

{

тип_элемента1 имя_элемента1;

тип_элемента2 имя_элемента2;

тип_элемента3 имя_элемента3;

};

К членам объединения можно обращаться так же, как и к членам структур, либо через операцию «точка», либо через операцию «->» – для указателей:

union many_types

(

char c[4];

int ivalue[2];

float fvalue;

} type1;

type1.fvalue=1.5;

printf(“%i %i”,type1.ivalue[0],type1.ivalue[1]);

Inline методы.

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

Пример:

inline double math_operation::getSquareRoot()

{

return sqrt(data);

}

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

Указатель this.

При описании класса автоматически объявляется переменная с именем this. Она указывает на текущий экземпляр класса:

ИмяКласса *this;

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

Конструкторы и деструкторы.

Особенность ООП в том, что некоторые методы выполняются неявно. К ним относятся конструктор и деструктор.

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

конструктор без параметров (используемый по умолчанию) и

конструктор, создающий копию объекта (копиконструктор).

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

Деструктор вызывается при уничтожении объекта. Он обычно используется для освобождения памяти. Деструктор имеет имя, совпадающее с именем класса, но впереди имени ставится знак ‘~’ (тильда), параметров не имеет.

Примеры:

class coins

{

int number;

public:

coins(){number=0;}

coins(int n){number=n;}

coins(coins &c){number=c.number;}

~coins(){cout<<”Finish\n”;}

int convertToRoubles(){return number*0.01;}

};

 

class stringOperation

{

char *str;

int lenght;

public:

stringOperation(){str=NULL;n=0;}

stringOperation(int n){str=new char[n];lenght=n;}

stringOperation(stringOperation &a)

{

       this(a.n);

       memcpy(str,a.str,n);

}

~stringOperation(){delete str;}

void indata()

{

cin>>lenght;

for(int i=0;i<lenght;i++)cin>>str[i];

}

void outdata()

{

cout<<lenght<<newline;

for(int i=0;i<lenght;i++)cout<<str[i];

cout<<newline;

};

 

Перегрузка методов класса.

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

Пример:

class module

{

public:

int mod(int n){return abs(n);}

double mod(double n){return fabs(n);}

};

void main()

{

module m;

int a=-10;

cout<<m.mod(a);

double b=-1.5;

cout<<m.mod(b);

}

Перегрузка операций.

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

Синтаксис метода, перегружающего операцию:

ВозвращаемыйТип operator перегружаемаяОперация(параметры){код}

Пример:

coins coins::operator+(coins a)

{

coins res;

res.number=this->number+a.number;

return res;

}

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

Вариант A.

Разработайте класс "Вектор", определите набор основных операций между ними. Умножение векторов определите как скалярное произведение векторов  и  в эвклидовой метрике в :

Предусмотрите возможности сохранения векторов на диске и восстановления их из файла.

Вариант В.

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

преобразованиями

Вариант C.

См. вариант B. Для преобразований:

Виртуальные функции

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

Пример:

Class Base

{

public:

virtual void virt(){cout<<”From Base, virt.”;}

void nonVirt(){cout<<”From Base, non virt.”;}

};

class Derived:public Base

{

public:

void virt(){cout<<”From Deriver, virt.”;}

void nonVirt(){cout<<”From Derived, non virt.”;}

};

void main()

{

Base *bp=new Derived;//Базовый указатель ссылается на произв.

bp_>virt();//Вызов виртуальной ф-ции произв. класса.

bp_>nonVirt();//Вызов невиртуальной ф-ции базового класса.

}

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

bp_>Base::virt();//Вызов виртуальной ф-ции произв. класса.

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

Виртуальная функция в базовом классе может быть определена как чистая. Для этого необходимо вместо кода этой функции написать “=0”. Класс, содержащий подобные функции называется абстрактным. Для такого класса невозможно создать представителя класса. Производный класс обязан содержать описание чистой функции.

Классы iostream.

Все объекты ввода/вывода, описанные в библиотеке iostream, используют оди и тот же базовый класс ios (за исключением классов буферизованных потоков). Эти производные классы делятся на 4 категории.

Классы потокового ввода

istream Универсальный класс ввода, или родительский класс для других производных потоковых классов ввода. ifstream Ввод из файлов. istream_withassign Ввод из потока cin. istrstream Ввод из строки.

Классы потокового вывода

ostream Универсальный класс вывода, или родительский класс для других производных потоковых классов вывода. ofstream Вывод в файлы. ostream_withassign Вывод в потоки cout, cerr и clog. ostrstream Вывод в строку.

Потоковый ввод-вывод.

Используемый в следующем примере класс ifsteam:

#include <fstream.h>

void main()

{

char one_line[80];

ifstream my_input_stream(“iputfile.cpp”,ios::in);

while(my_input_stream)

{

my_input_stream.getline(one_line,sizeof(one_line),’*’);

cout<<endl<<one_line;

}

my_input_stream.close();

}

Для объекта my_input_stream можно использовать методы open(), rdbuf() из класса ifstream и ряд методов из родительского класса istream: gcount(),get(), getline(), ignore(), peek(), putback(), read(), seekg(), tellg().

При создании объекта вызывается конструктор, которому передается имя файла, а также один или несколько режимов ввода, задаваемые константами, предопределенными в классе ios (ios::in ios::binary ios::nocreate). Константы объединяются с помощью операции побитового или “|”. Значение дескриптора файла можно использовать в логических проверках. При достижении конца файла оно устанавливается в ноль (условие EOF).

Метод getline() читает текстовые строки из входного потока (знак “*” является разделителем строк).

 

Классы ofstream позволяют выполнять вывод в поток streambuf:

#include <fstream.h>

#include <string.h>

void main()

{

int i=0;

long ltellp;

char sample[40]=”Sample string\n”;

ofstream my_out_stream(“outfile.out”,ios::out);

while(sample[i]!=0)

{

       my_out_stream.put(sample[i]);

ltellp=my_out_stream.tellp();

cout<<”\ntellp value: “<<ltellp;

i++;

}

my_out_stream.write(sample,strlen(sample));

ltellp.my_out_stream.tellp();

cout<<”\ntellp after write: “<<ltellp;

my_out_stream.close();

}

Обратите вни


Поделиться с друзьями:

История развития хранилищ для нефти: Первые склады нефти появились в XVII веке. Они представляли собой землянные ямы-амбара глубиной 4…5 м...

Организация стока поверхностных вод: Наибольшее количество влаги на земном шаре испаряется с поверхности морей и океанов (88‰)...

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

Индивидуальные и групповые автопоилки: для животных. Схемы и конструкции...



© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!

0.342 с.