Динамическое управление памятью (new, delete).




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

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

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

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

Для выделения памяти под любую переменную используется операция new [2]:

указатель = new имя_типа инициализатор

Эта операция позволяет выделить и сделать доступным свободный участок в основной памяти, размеры которого соответствуют типу данных, определяемому именем типа. В выделенный участок памяти заносится значение, определяемое инициализатором, который не является обязательным элементом. В случае успешного выполнения операция new возвращает адрес начала выделенного участка памяти. Если участок нужных размеров не может быть выделен (нет памяти), то операция new возвращает нулевое значение указателя (NULL). Необязательный параметр инициализатор – это выражение в круглых скобках. Указатель должен ссылаться на тот же тип, что имя_типа в операции new.

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

Delete указатель

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

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

23.Динамические массивы в языке программирования С++.

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

24.Использование указателей при обработке массивов в языке программирования С++.

Известно, что данные хранятся в ячейках памяти компьютера. Все ячейки памяти пронумерованы. Номера ячеек памяти называются адресами. Указатели используются для работы с адресами. Указатель – это некоторое си мволическое представление адреса. Это означает, что будем работать с переменными, хранящими эти адреса. Описываются такие переменные следующим образом:

<тип> *<идентификатор>;

Такое описание синтаксически отличается от описания простой переменной только наличием знака * перед именем переменной. Как видно из описания, указатель всегда связывается с переменной какого-то определенного типа. Это позволяет определить, сколько байт памяти необходимо выделить по указанному адресу. В переменной типа указатель хранится адрес первого байта, выделенного участка памяти.

Над указателями можно выполнять следующие операции:

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

· Значение указателя можно увеличить или уменьшить на константную величину

· Указателю можно присвоить значение адреса. Для получения адреса используется знакомый значок &

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

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

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

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


25.Описание функций, фактические и фоpмальные паpаметpы в языке программирования С++.

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

В программе на языке С++ описание функций может располагаться либо до функции main, либо после функции main. Никакая функция не может быть описана внутри другой функции. Кроме того, функции могут быть описаны в отдельном файле и подключены к программе с помощью директивы препроцессора include. Каждая функция описывается один раз, а вызываться на выполнение может многократно. В языке C++ описание должно обязательно предшествовать вызову функции. Если функция описана после функции, из которой она вызывается, то до вызова функции должен быть помещен прототип функции. Прототип функции – это заголовок функции, завершающийся точкой с запятой (функция должна быть декларирована).

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

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

Заголовок функции

Тело функции

Общая форма записи заголовка функции:

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

Здесь <имя> - правильный идентификатор, который используется для обращения к функции;

<тип> - тип возвращаемого функцией результата;

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

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

Вызов функции производится при помощи оператора вызова функции:

<имя >(<список фактических параметров>);

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

Следует заметить, что таким образом вызываются функции типа void, т. е. функции, не возвращающие никакого значения. Функции же, возвращающие значения типа int, float и т. д., вызываются упоминанием имени в выражении аналогично стандартным функциям sin, cos и другим. Поэтому в теле таких функций обязательно должен присутствовать оператор возврата return. После ключевого слова return записывается выражение, значение которого вставится вместо имени функции в точке вызова. Функция не может возвращать массив или функцию. В качестве результата, возвращаемого функцией, могут быть значения только простого и ссылочного типа. Оператор return приводит к немедленному выходу из функции. Если функция имеет тип void, то оператор return может быть использован без возвращаемого значения.

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

· количество формальных параметров должно быть равно количеству фактических параметров;

· порядок следования фактических и формальных параметров должен быть один и тот же;

· тип каждого фактического должен совпадать с типом соответствующего формального параметра.

фактический параметр — аргумент, передаваемый в функцию при ее вызове;

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

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

По значению.

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

По адресу.

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

Можно заметить, что передача параметра по адресу является частным случаем передачи по значению: передаваемым значением является адрес, по которому можно найти другое значение — значение переменной x.

По ссылке.

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

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

Если функция возвращает значение по ссылке (например, в виде «return *this;»), то её вызов можно использовать слева от оператора присваивания.

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

Таким образом можно ожидать, что примерная программа напечатает (если закоментировать ошибочную строку) «0010 022 233 333».

27.Строки символов в языке программирования С++.

Символьная переменная – это величина размером в 1 байт, которая используется для представления литер и целых чисел в диапазоне от 0 до 255 или от –128 до 127. Диапазон зависит от того, знаковая это переменная или нет. Символьные константы заключаются в апостро фы. Например, “a”, ”=”, “9”. Используется специальный код для перевода чисел в символы. Чаще всего это код ASCII (американский стандартный код обмена информацией). Латинская буква А имеет код 65, а русская буква А – 128. Поэтому при работе с русским алфа витом, необходимо использовать беззнаковые целые (unsigned char), диапазон представления которых лежит в интервале от 0 до 255. Буквы латинского алфавита в таблице ASCII расположены по порядку. Буквы русского алфавита имеют разрыв, но их код возрастает в соответствии с алфавитом. Некоторые символы не печатаются, в этом случае используется номер символа с обратной косой чертой, например “\007” (этот символ используется для выдачи короткого звукового сигнала) или “\n” (перевод курсора на новую строку).

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

Здесь следует отметить, что при подсчете символов будут учитываться все символы, включая пробелы и перевод курсора на новую строку “\n” (при нажатии клавиши enter). Кроме того, здесь впервые используется потоковый ввод-вывод. Для того чтобы воспользоваться потоковым вводом- выводом, в текст программы включена директива препроцессора

#include <iostream.h>

Символьные строки представляют один из наиболее полезных и важных типов данных. В языке С++ символьная строка является символьным массивом, который заканчивается нуль-символом (\0). Если строка должна содержать N символов, то в описании нужно указать N+1 элемент.

Функция gets() получает строку с клавиатуры. Функция читает символы до тех пор, пока не встретит символ новой строки (“\n”), который создается при нажатии клавиши enter. Функция берет все символы до “\n” и присоединяет к ним символ “\0”. Аргументом функции должен быть указатель на строку символов. Функция puts() выводит строку, указатель на которую является аргументом этой функции, на экран. Функция puts() прекращает свою работу, как только встретит нуль-символ (поэтому надо следить, чтобы он был), и заменяет его символом новая строка.

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

· strlen (s) - определяет длину строки (без нуль-символа). s – указатель на строку символов.

· strcat (s1, s2) – объединяет две с троки. s1, s2 – указатели на строку символов. Копия второй строки присоединяется к концу первой, и это объединение становится новой первой строкой. Строка s2 остается без изменения, а s1должна быть достаточно большой, чтобы разместить две строки.

· strcmp (s1, s2) – сравнивает содержимое двух строк. s1, s2- указатели на строку символов. Эта функция возвращает 0, если строки одинаковые. Если строки разные, то функция возвращает разницу в кодах у первой пары несовпадающих символов.

· strcpy (s1, s2) – копирова ние строки: строка, на которую указывает второй аргумент, копируется в строку, на которую указывает первый.

· strchr (s, c) – ищет в строке s первое вхождение символа с и возвращает указатель на этот символ, если не обнаружит, то возвращает NULL.

· strstr (s1, s2) – ищет в строке s1 первое вхождение подстроки s2 и возвращает указатель на найденную подстроку, если не обнаружит, то возвращает NULL.

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

Для записи строки в файл используется функция fputs, аналогичная puts, но имеющая в качестве второго параметра указатель на файл, в который намерены писать строку символов. Функция fgets, аналогичная gets, служит для чтения из файла строки символов и имеет следующий синтаксис:

char *fgets(char *s, int n, FILE * stream)

Эта функция считывает из файла с указателем stream в строку s символы до тех пор, пока не будет выполнено одно из условий:

· начнется новая строка;

· достигнут конец файла;

· прочитано n-1 символов

fgets (s, 20, in);// Читается не более 20 символов

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

28.Стpуктуpы и объединения в языке программирования С++.

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

Объявление структуры:

struct < имя типа >{

< сп. полей >

};

Здесь struct – ключевое слово; < имя типа > – правильный идентификатор; < сп. полей > – список полей, представляющий собой последовательность разделов, между которыми ставится точка с запятой.

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

Для структур одного типа можно проверить выполнение отношения равенства или неравенства. Как и в случае массивов, допустимы операции сравнения = = и!=.

Структуры могут быть элементами массива.

Поле структуры само может быть структурой.

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

union < имя типа >{

< сп. полей >

};

Здесь < имя типа > – правильный идентификатор; < сп. полей > – список полей, представляющий собой последовательность разделов, между которыми ставится точка с запятой.

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

29.Битовые поля в языке программирования С++.

В отличие от других языков программирования язык Си обеспечивает доступ к одному или нескольким битам в байте или слове. Внутри структур и объединений могут в качестве их компонентов использоваться битовые поля. Каждое битовое поле представляет целое или беззнаковое целое значение, занимающее в памяти фиксированное число битов (от 1 до 16). Битовые поля могут быть только элементами структур, объединений и классов, т. е. они не могут быть самостоятельными объектами программ. Битовые поля не имеют адресов, нет указателей и ссылок на битовые поля. Они не могут объединять-ся в массивы. Назначение битовых полей – обеспечить удобный доступ к от-дельным битам данных. Чаще всего битовые поля используют при работе с флажками, которые могут принимать только два значения, что позволяет экономить память.

Синтаксис описания структуры с битовыми полями следующий:

struct <имя>{

<тип поля> имя поля1: длина в битах;

<тип поля> имяполя2: длина в битах;

<тип поля> имяполяN: длина в битах;

}

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


30.Классы памяти. Область действия имен в языке программирования С++.

В С++ существуют 3 класса памяти.

1) Статическая память - статические данные, размещаемые в сегменте данных;

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

3) динамические данные, явно размещаемые в динамической памяти с помощью операций new и delete.

Статические объекты существуют в течение всего времени выполнения программы. К ним относятся глобальные и локальные переменные, объявленные со служебным словом static.

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

Локальные переменные, не объявленные как static, являются автоматическими. Такие объекты начинают свое существование при объявлении его имени в блоке и заканчивают его при завершении этого блока. Если автоматический объект явно не инициализирован, то его значение до присвоения не определено.

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

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

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

В языке С++ различают четыре класса памяти:

· автоматический (auto)

· внешний (extern)

· статический (static)

· регистровый (register)

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

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

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

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

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

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

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

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

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

31.Текстовые файлы в языке программирования С++.

Под файлом понимается именованная область внешней памяти или логическое устройство – потенциальный источник или приемник информации [10]. Основное отличие внешней памяти ЭВМ от оперативной памяти? возможность сохранения информации при отключении ЭВМ. Информация сохраняется в виде файлов, доступ к которым поддерживает операционная система ЭВМ. Поддержка операционной системы состоит в том, что в ней имеются средства:

· создания файлов;

· уничтожения файлов;

· поиска файлов на внешнем носителе;

· чтения и записи из файлов и в файлы;

· открытия файлов;

· закрытия файлов;

· позиционирования файлов.

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

Любой файл в С++ имеет три характерные особенности:

· • у файла есть имя, это дает возможность работать с несколькими файлами одновременно;

· • содержит компоненты одного типа (типом может быть любой тип, кроме файлового);

· • длина вновь создаваемого файла никак не ограничена при объявлении и ограничивается лишь емкостью внешних устройств памяти.

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

FILE *< имя >;

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

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

Текстовый файл можно представить как набор строк произвольной длины. Для деления на строки используется управляющий символ ’\n’. Он является файлом последовательного доступа. Логически текстовый файл можно представить как именованную цепочку байтов, имеющую начало и конец. Чтение (или запись) из файла (в файл) ведется байт за байтом от начала к концу. Перед первым обращением к функциям ввода-вывода указатель файла стоит в его начале и указывает на первый компонент. После каждого чтения или записи указатель сдвигается на заданное количество байт. Такой способ доступа называется последовательным. Текстовые файлы оказываются переносимыми с одного типа компьютера на другой, если символы, содержащиеся в файле, принадлежат стандартному набору символов (т. е. не используются дополнительные символы, такие, например, как символы псевдографики фирмы IBM).

Рассмотрим текстовые файлы. Каждой программе доступны два стандартных файла stdin (клавиатура) и stdout (экран). Это - текстовые файлы. Любые другие файлы становятся доступными после выполнения специальных процедур. Рассмотрим основные функции для работы с текстовыми файлами.

Функция открытия файла:

FILE *fopen (char *filename, char *type)

Эта функция возвращает указатель на файл, который открывается. Если файл открыть нельзя, то функция возвращает пустой указатель NULL. char *filename – указатель на строку символов, содержащую имя файла и, если необходимо, путь к нему. char *type – указатель на строку символов, определяющую тип открываемого файла. Допустимы следующие значения этой переменной:

· ”r” - открыть уже существующий файл на ввод;

· ”w” - cоздать новый файл или очистить уже существующий файл и открыть его на вывод;

· ”a” - cоздать новый файл для вывода или осуществить вывод в конец уже существующего файла;

· ”r+”- открыть уже существующий файл для обновления, которое будет проводиться с начала файла;

· ”w+”- cоздать новый файл или очистить уже существующий файл для обновления его содержимого;

· ”a+”- cоздать новый файл или подстроиться в конец существующего для обновления его содержимого.

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

При заполнении файла после последней записи автоматически помещается невидимый специальный признак "конец файла" (end of file). Существует функция feof(f), тестирующая конец файла. Функция feof(f) возвращает значение истина, если действительно встретился признак "конец файла"; пока это не произойдет, значение feof(f) будет ложь.

fclose(FILE * stream) - функция закрытия файла, на который указывает указатель на файл stream. Функция fclose() выполняется автоматически по отношению ко всем открытым файлам при нормальном за-вершении программы.

Для чтения и записи информации из файла или в файл используется очень много функций. Например, функции fscanf и fprintf, анало-гичные уже знакомым функциям scanf и printf, но в качестве первого параметра в них выступает указатель на файл.

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

32.Структурное программирование в языке программирования С++.

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

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

Типы управляющих структур:

· последовательность;

· альтернатива (условие выбора);

· цикл.

Распространены две методики (стратегии) разработки программ, относящиеся к структурному программированию:

· программирование «сверху вниз»;

· программирование «снизу вверх».

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

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

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

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



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2018-01-08 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: