WWW.DISS.SELUK.RU

БЕСПЛАТНАЯ ЭЛЕКТРОННАЯ БИБЛИОТЕКА
(Авторефераты, диссертации, методички, учебные программы, монографии)

 

Pages:     | 1 | 2 || 4 |

«Т, А. Павловская C/C++ Программирование на языке высокого уровня Допущено Министерством образования Российской Федерации в качестве учебника для студентов высших учебных заведений, обучающихся по направлению Информатика ...»

-- [ Страница 3 ] --

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

Корректность приведения проверяется автоматически, в случае несовпадения порождается исключение bad^cast:

#include #include class B{ public: virtual void f l ( ) { } ;

class C: public B{ public: void f2(){.. };

void demo(B& p){ C& с = dynamic_cast(p):

catch(bad_cast){ int main(){ Перекрестное преобразование Операция dynamic_cast позволяет выполнять безопасное преобразование типа между производными классами одного базового класса, например:

#include #1nclude class B{ class C: public B{ public: void f2(){.. }:

class D: public B{... }:

void demo(D* p){ C* с = dynamic_cast(p):

i n t main(){ Классы С и D являются производными от класса В. Функции demo передается ука­ затель на класс D, являющийся на самом деле указателем на «братский» для него класс С, поэтому динамическое преобразование типа из D в С в функции demo за­ вершается успешно.

ПРИМЕЧАНИЕ

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

При необходимости можно осуществить преобразование между базовыми клас­ сами одного производного класса, например:

#include finclude class B{ public: virtual void f2(){... }:

class D: public B. public C{}:

void demo(B* b){ С* с = dynamic_cast(b);

if(c)c->f2();

int ma1n(){ Класс D является потомком В и С, поэтому содержит методы обоих классов. Если в функцию demo передается на самом деле указатель не на В, а на D, его можно пре­ образовать к его второму базовому классу С.

Операция static_cast Операция stat1ccast используется для преобразования типа на этапе компиля­ ции между:

• целыми типами;

• целыми и вещественными типами;

• целыми и перечисляемыми типами;

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

Формат операции:

static_cast (выражение) Результат операции имеет указанный тип, который может быть ссылкой, указа­ телем, арифметическим или перечисляемым типом.

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

float f = 100:

int 1 = static_cast (f):

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

Операция static_cast позволяет выполнять преобразования из производного класса в базовый и наоборот без ограничений:

class В{};

class С: public В{}:

В *Ьр = stat1c_cast(c): / / Производный -> базовый С &ср = stat1c_cast(b): / / Базовый -> производный Преобразование выполняется при компиляции, при этом объекты могут не быть полиморфными. Программист должен сам отслеживать допустимость дальней­ ших действий с преобразованными величинами.

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

Операция reinterpret_cast Операция reinterpret_cast применяется для преобразования не связанных между собой типов, например, указателей в целые или наоборот, а также указателей типа void* в конкретный тип. При этом внутреннее представление данных оста­ ется неизменным, а изменяется только точка зрения компилятора на данные.

Формат операции:

reinterpret_cast (выражение) Результат операции имеет указанный тип, который может быть ссылкой, указа­ телем, целым или вещественным типом.

Пример:

char *р = re1nterpret_cast (malloc(100)):

long 1 = reinterpret^cast (p);

Различие между static^cast и re1nterpret_cast позволяет компилятору произво­ дить минимальную проверку при использовании stat1c_cast, а программисту — обозначать опасные преобразования с помощью re1nterpret_cast. Результат пре­ образования остается на совести программиста.

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

Формат операции typeid:

typeid (тип) typeid (выражение) Операция принимает в качестве параметра имя типа или выражение и возвраща­ ет ссылку на объект класса type^info, содержащий информацию о типе. Если опе­ рация не может определить тип операнда, порождается исключение bad_typeid.

^ В старых версиях компиляторов этот класс может называться Typeinfo или typeinfo.



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

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

Операцию typeid можно использовать как с основными, так и с производными типами данных.

Класс type_1nfo описан в заголовочном файле следующим образом:

class type_info{ publicvirtual 4ype_1nfo():

bool operator==(const type_1nfo& rhs) const:

bool operator!=(const type_1nfo& rhs) const:

bool beforeCconst typeJnfo& rhs) const:

const char* nameO const:

private:

typeJnfo(const type_info& rhs):

typeJnfo& operator=(const type_info& rhs):

Метод name возвращает указатель на строку, представляющую имя типа, описы­ ваемого объектом типа typejnfo.

Виртуальный деструктор делает класс typeinfo полиморфным.

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

Операции == и ! = позволяют сравнивать два объекта на равенство и неравенство, а функция before выполняет побуквенное сравнение имен двух типов. Для срав­ нения используется конструкция вида:

typeid(Tl).before(typeicl(T2)) Если имя типа Т1 лексикографически предшествует имени Т2, результат будет ис­ тинным.

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

#include class В{ class С: public В{ public: virtual void some_method(){... }:

void demoCB* р){ i f (type1d(*p) == typeid(C)) dynamic_cast(p)->somG_method():

i n t ma1n(){ Информацию о типе полезно использовать и в диагностических целях:

void pr1nt_type(some_obj *р){ cout « type1d(*p).name();

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

ГЛАВА Рекомендации по программированию в этой части были рассмотрены объектно-ориентированные возможности языка C++, и теперь пришло время остановиться на проблемах, которые возникают в процессе написания программ: какие средства языка предпочтительнее выбирать в разных случаях, на что обратить особое внимание, чего нужно избегать, чтобы программа получилась эффективной и легко сопровождаемой.

Однозначные рекомендации, как всегда, дать невозможно — только понимание механизма работы C++ позволит грамотно его использовать.

Создание любого программного продукта начинается с процесса проектирова­ ния, и одна из первых задач, возникающих при этом, — определить, должна про­ грамма быть объектно-ориентированной или нет. Объектно-ориентированное программирование, примененное к задаче, в которой в нем нет необходимости, только увеличит объем программы и сложность ее написания. Если в процессе анализа постановки задачи выясняется, что необходимости в иерархии классов нет, чаще всего можно обойтись структурным подходом. Б. Страуструп считает, что «везде, где не нужно более одного объекта определенного типа, достаточно стиля программирования с сокрытием данных при помощи модулей».

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

Технологии проектирования программ посвящено много литературы, и освещение этого вопроса не входит в задачу данной книги. Тем, кто собирается приниматься за серьезные программные проекты, рекомендуется предварительно изучить став­ шие классическими книги Ф. Брукса [6], Г. Буча [7] и Б. Страуструпа [17]. Далее рассматриваются вопросы, на которые следует обращать внимание на следующем этапе создания программы — в процессе написания программного кода.

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

Не следует определять методы типа get/set для всех скрытых полей класса — это все равно, что открыть к ним доступ, только более сложным способом. Важно помнить, что поля класса вводятся только для того, чтобы реализовать свойства класса, представленные в его интерфейсе с помощью методов. Конечно, нет ниче­ го плохого в том, чтобы установить или получить значение некоторого поля с по­ мощью метода, если таким образом реализуется свойство класса (таким образом, код будет тот же, а его смысл — совсем другим).

Не нужно расширять интерфейс класса без необходимости, «на всякий случай», поскольку увеличение количества методов ведет к трудности понимания класса пользователем^. В идеале интерфейс должен быть полным, то есть предоставлять возможность выполнить любые разумные действия с классом, и минимальным — без дублирования и пересечения возможностей методов.

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

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

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

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

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

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

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

Если какая-либо операция перегружена, следует, если возможно, перегрузить и аналогичные операции, например, +, += и ++ (компилятор этого автоматически не сделает). При этом операции должны иметь ту же семантику, что и их стандарт­ ные аналоги.

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

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

Кроме того, дииамическая память, выделенная в конструкторе объекта, должна освобождаться в его деструкторе. Невыполнение этого требования приводит к утечкам памяти. Удаление нулевого указателя безопасно (при этом ничего не происходит), поэтому если конструкторы, конструкторы копирования и опера­ ция присваивания написаны правильно, любой указатель либо ссылается на вы­ деленную область памяти, либо равен нулю, и к нему можно применять delete без проверки.

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

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

class Х{ const X & operator=(const X & г ) ;

const X & X::operator=(const X & г){ if(th1s != &г){ В конструкторах для задания начальных значений полям рекомендуется исполь­ зовать инициализацию у а не присваивание:

class Х{ // Вариант конструктора с присваиванием:

X::X(const char * str){ s = str: } // Вариант конструктора с инициализацией:

X::X(const char * str): s(str){} Инициализация более универсальна, так как может применяться в тех случаях, когда присваиванием пользоваться нельзя (например, при задании значений константным полям или ссылкам). Кроме того, она выполняется более эффек­ тивно, потому что создание объекта в C++ начинается с иниц^1ализации его по­ лей конструктором по умолчанию, после чего выполняется вызываемый конст­ руктор. Таким образом, для первого варианта рассмотренного примера сначала будет вызван конструктор класса string по умолчанию, и только потом будет вы­ полнено присваивание, в то время как второй вариант позволяет сразу же вы­ звать нужный конструктор. Для сложных классов, составляющих иерархию, раз­ ница между приведенными вариантами гораздо значительнее.

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

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

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

class Х{ / / Конструктор копирования:

class Y: public Х{ // Конструктор копирования:

YCconst Y & г): Х(г). s(r.s){} Операция присваивания не наследуется, поэтому она должна быть определена в производных классах. При этом из нее следует явным образом вызывать соответ­ ствующую операцию базового класса (см. с. 204).

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

Открытое наследование класса Y из класса X означает, что Y представляет со­ бой разновидность класса X, то есть более конкретную, частную концепцию. Ба­ зовый класс X является более общим понятием, чем Y^ Везде, где можно ис­ пользовать X, можно использовать и Y, но не наоборот (вспомните, что на место ссылок на базовый класс можно передавать ссылку на любой из производных).

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

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

При переопределении виртуальных методов нельзя изменять наследуемое значе­ ние аргумента по умолчанию, поскольку по правилам C++ оно определяется ти­ пом указателя, а не фактическим типом объекта, вызвавшего метод:

#1nclude class Х{ class Y: public X{ i n t main(){ px->fun(): // Выводится ^ Например, каждый программист — человек, но не каждый человек — программист.

py->fun(); / / Выводится О Невиртуальные методы переопределять в производных классах не рекомендуется, поскольку производные классы должны наследовать свойства базовых. Иными словами, невиртуальный метод инвариантен относительно специализации, то есть сохраняет те свойства, которые должны наследоваться из базового класса независимо от того, как конкретизируется (специализируется) производный класс. Специализация производного класса достигается добавлением новых ме­ тодов и переопределением существующих виртуальных методов.

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

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

class Y{ Вложение представляет отношения классов «Y содержит X» или 0) cout « "s2 > s3 " « endl:

i f (sl.compare(7. 4. s3) < 0) i f (sl.compare(7. 4. s3. 0.4 ) == 0) cout « "sl[7-10] == s3[0-3] " « endl:

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

sl= лесная королева s3= корова sl[7-10] < s sl[7-10] == s3[0-3] Получение характеристик строк в классе string определено несколько функций-членов, позволяющих полз^ить длину строки и объем памяти, занимаемый объектом:

size_type sizeO const: // Количество элементов строки size_type lengthO const: // Количество элементов строки size_type max_size() const: // Максимальная длина строки size_type capacityO const: // Объем памяти, занимаемый строкой bool emptyO const: / / Истина, если строка пустая ГЛАВА Контейнерные классы Контейнерные классы — это классы, предназначенные для хранения данных, ор­ ганизованных определенным образом. Примерами контейнеров могут служить массивы, линейные списки или стеки. Для каждого типа контейнера определены методы для работы с его элементами, не зависящие от конкретного типа данных, которые хранятся в контейнере, поэтому один и тот же вид контейнера можно использовать для хранения данных различных типов. Эта возможность реализо­ вана с помощью шаблонов классов, поэтому часть библиотеки C++, в которую входят контейнерные классы, а также алгоритмы и итераторы, о которых будет рассказано в следующих разделах, называют стандартной библиотекой шаблонов (STL — Standard Template Library).

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

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

STL содержит контейнеры, реализующие основные структуры данных, исполь­ зуемые при написании программ — векторы, двусторонние очереди, списки и их разновидности, словари и множества. Контейнеры можно разделить на два типа:

последовательные и ассоциативные.

Последовательные контейнеры обеспечивают хранение конечного количества од­ нотипных величин в виде непрерывной последовательности. К ним относятся векторы (vector), двусторонние очереди (deque) и списки (list), а также так на­ зываемые адаптеры, то есть варианты, контейнеров — стеки (stack), очереди (queue) и очереди с приоритетами (priority^queue).

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

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

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

Эти контейнеры построены на основе сбалансргрованных деревьев. Существует пять типов ассоциативных контейнеров: словари (тар), словари с дубликатами (multlmap), множества (set), множества с дубликатами (multiset) и битовые мно­ жества (bitset).

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

Центральным понятием STL является шаблон, поэтому перед тем, как присту­ пить к изучению материала этой главы, рекомендуется убедиться, что это по­ нятие не представляет для читателя загадку (см. «Шаблоны функций», с. 85, и «Шаблоны классов», с. 211). Также необходимо знать, что такое пространства имен (с. 99), перегрузка функций (с. 83) и перегрузка операций (с. 189).

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

Практически в любом контейнерном классе определены по.71я перечисленных ниже типов:

value_type s1zetype Iterator constjterator Константный итератор reverse_1terator Обратный итератор const_reverse_1terator reference const_reference key_type key_compare Итератор является аналогом указателя на элемент. Он используется для про­ смотра контейнера в прямом или обратном направлении. Все, что требуется от итератора — уметь ссылаться на элемент контейнера и реализовывать операцию перехода к его следующему элементу. Константные итераторы используются то­ гда, когда значения соответствующих элементов контейнера не изменяются (бо­ лее подробно от итераторах рассказывается в разделе «Итераторы», с. 328).

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

Метод iterator begInO, const_iterator beginO const iterator endO, reverseiterator rbeginO, const_reverseJterator rbeginO const reversejterator rendO. Указывают па элемент, следующий const_reverse_iterator rendO const за последним, в обратной последовательности В каждом контейнере эти типы и методы определяются способом, зависящим от их реализации.

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

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

STL определяется в 13 заголовочных файлах:

Последовательные контейнеры Векторы (vector), двусторонние очереди (deque) и списки (list) поддерживают разные наборы операций, среди которых есть совпадающие операции. Они могут быть реализованы с разной эффективностью:

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

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

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

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

Список эффективно реализует вставку и удаление элементов в произвольное ме­ сто, но не имеет произвольного доступа к своим элементам.

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

#1nc1ude #1nclucle using namespace std:

1nt main(){ Ifstream in ("1npnum.txt");

while ( in » x. lin.eofO) v.pushback(x):

for (vector::iterator i = v.beginO; i !- v.endO: ++i) Поскольку файл содержит целые числа, используется соответствующая специа­ лизация шаблона vector ~ vector. Для создания вектора v используется кон­ структор по умолчанию. Организуется цикл до конца файла, в котором из него считывается очередное целое число. С помощью метода push_back оно заносится в вектор, размер которого увеличивается автоматическиi.

^ Размер вектора не изменяется каждый раз при добавлении элемента, это было бы нера­ ционально. Он увеличивается по определенному алгоритму, которым можно управлять (см. с. 301).

Для прохода по всему вектору вводится переменная i как итератор соответст­ вующего типа (напомню, что операция :: обозначает доступ к области видимо­ сти, то есть здесь объявляется переменная i типа «итератор для конкретной спе­ циализации шаблона»). С помощью этого итератора осуществляется доступ ко всем по порядку элементам контейнера, начиная с первого. Метод beginO возвра­ щает указатель на первый элемент, метод end О — на элемент, следующий за по­ следним. Реализация гарантирует, что этот указатель определен.

Сравнивать текущее значение с граничным следует именно с помощью операции !=, так как операции < или pl\n":

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

p2: 20 12. Заголовочный файл при использовании или подключается автоматически.

Словари (map) в словаре (тар), в отличие от словаря с дубликатами (multimap), все ключи долж­ ны быть уникальны. Элементы в словаре хранятся в отсортированном виде, по­ этому для ключей должно быть определено отношение «меньше». Шаблон сло­ варя содержит три параметра: тип ключа, тип элемента и тип функционального объекта, определяющего отношение «меньше» (функциональные объекты рас­ сматривались на с. 195):

template class map{ typedef pair value_type:

e x p l i c i t map(const Compare& comp = CompareO):

mapdnputlter f i r s t. Inputlter last, const Compare& comp = CompareO):

Как видно из приведенного описания (оно дано с сокращениями), тип элементов словаря value_type определяется как пара элементов типа Key и Т.

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

Как и для всех контейнеров, для словаря определены деструктор, операция при­ сваивания и операции отношения. Итераторы словаря перечислены в табл. 12.

Для доступа к элементам по ключу определена операция [ ]:

Т& operator[](const Key & х);

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

#1nclude #1nclucle #1nclude #1nclude using namespace std;

typedef map map_sl: / / 1nt main(){ ifStream in("phonebook"):

map_sl : iterator i;

for (i =ml.begin(): i !=ml.end(); i++) cout « (*i).first « " " « (*i).second « endl;

cout « "Второй элемент: ";

cout « (*i).first « " " « (*i).second « endl;

cout « "Vasia: " « mlC'Vasia"] « end!; // Вывод элемента по ключу Для улучшения читаемости программы введено более короткое обозначение типа словаря (оператор, помеченный // 1). Сведения о каждом человеке располо­ жены в файле phonebook на одной строке: сначала идет номер телефона, затем че­ рез пробел фамилия:

1001002 Petya К.

3563398 Ivanova N.M.

1180316 Vovochka 2334476 Vasia Для итераторов словаря допустимы операции инкремента и декремента, но не операции + и -. Ниже приведен результат работы программы (обратите внима­ ние, что словарь выводится в упорядоченном виде):

Petya К. Ivanova N.M. Vovochka Vasia Ivanova N.M. Petya K. Petya P. Vasia Vovochka Второй элемент: Petya К. Vasia: Для поиска элементов в словаре определены следующие функции:

iterator fincKconst key_type& х):

constjterator fincKconst key_type& x) const:

iterator lower_bound(const key_type& x):

constjterator lower_bound(const keytype& x) const:

iterator upper_bouncl(const key_type& x):

constjterator upper_bound(const keyjype &x) const:

sizejype count (const keyjype& x) const:

Функция find возвращает итератор на найденный элемент в случае успешного поиска или end О в противном случае.

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

Функция lower^bound возвращает итератор на первый элемент, ключ которого больше X, или endO, если такого нет.

Добавим в приведенный выше пример операторы getlineCcin. str):

if (ml.find(str) != ml.endO) else{ cout « (*ml.upper_bound(str)).first « " " ;

cout « (*mLlower_bound(str)).first « " " ;

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

Petya М. / / Подчеркиванием обозначен ввод пользователя Petya Р. Petya Р.

Функция count возвращает количество элементов, ключ которых равен х (таких элементов может быть О или 1).

Для вставки и удаления элементов определены функции:

pair insertCconst value_type& x):

iterator insertCiterator position, const value_type& x):

template void insertdnputlter first. Inputlter last):

void erase(iterator position):

size_type eraseCconst key_type& x):

void erase(iterator first, iterator last):

Первая форма функции используется для вставки в словарь пары «ключ—зна­ чение». Функция возвращает пару, состоящую из итератора, указывающего на вставленное значение, и булевого признака результата операции: true, если запи­ си с таким ключом в словаре не было (только в этом случае происходит добавле­ ние), и false в противном случае (итератор указывает на существующую запись).

Время работы функции пропорционально логарифму колргчества элементов в сло­ варе.

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

Ниже приведено несколько примеров вставки в словарь, тип которого описан в предыдущем листинге:

m2.insert(map_sl: :valuetype("Lena". 3157725)):

str = "Anna":

num = 5536590:

m2.insert(makepair(str. num)):

num = 5530000:

/ / Попытка вставки существующей записи:

m2.insert(mal. Переход к елеГлава 13. Итераторы и функциональные объекты дующему элементу — с помощью операции инкремента ++. Для всех итераторов определены также присваивание, проверка на равенство и неравенство.

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

Пусть 1 и j — итераторы одного вида, х — переменная того же типа, что и элемент последовательности, п — целая величина. Тогда допустимы выражения:

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

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

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

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

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

• итератор не был инициализирован;

• контейнер, с которым он связан, изменил размеры или уничтожен;

• итератор указывает на конец последовательности.

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

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

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

template struct iterator_traits{ typedef typename Iter: :differGnce_type cl1fference_type:

typedef typename Iter::value_type value^type:

typedef typename Iter::pointer pointer;

typedef typename Iter::reference reference;

typedef typename Iter: :iterator_category iteratorcategory;

Ключевое слово typename необходимо для того, чтобы компилятор мог опознать Iter как имя типа. iterator_category — это тип итератора, который определяет, ка­ кие он поддерживает операции. Тип di f ference_type служит для выражения раз­ ности между двумя итераторами.

В заголовочном файле описаны следующие типы итераторов:

struct input_iterator_tag{};

struct output_iterator_tag{};

struct forwardJterator_tag: public inputJterator_tag{};

struct bidirectional_iterator_tag:

public forward_iterator_tag{};

struct random_accessJterator_tag:

public bi di recti onal_iteratortag{};

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

Для обычных указателей в целях повышения эффективности определены спе­ циализации шаблона iterator^traits (о специализациях шаблонов рассказыва­ лось на с. 220):

tempiate struct iterator_traits{ typedef ptrdiff^t differencetype;

typedef Т va1ue_type:

typedef Т* pointer;

typedef Т& reference:

typedef random_access_iterator_tag iterator_category:

Разность между двумя указателями имеет стандартный тип ptrd1ff_t, опреде­ ленный в. Аналогичная специализация шаблона введена и для типа const Т*.

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

distancednputlterator f i r s t. Inputlterator last);

Она возвращает значение типа di fference_type, представляющее собой разность между двумя итераторами. Эта функция для всех итераторов, кроме итераторов произвольного доступа, выполняется с использованием операции ++ за время, пропорциональное расстоянию между элементами контейнера, то есть довольно ресурсоемка. Аналогично работает и функция advance, которая применяется для реализации операции i += п:

void advance(InputIterator& i. Distance n);

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

Обратные итераторы Для двунаправленных итераторов и итераторов произвольного доступа опреде­ лены разновидности, называемые адаптерами итераторов. Адаптер, просматри­ вающий последовательность в обратном направлении, называется reverse_ iterator:

template class reversejterator ; public protected;

reverseJteratorO;

explicit reversejterator (It x);

template reverse_iterator(const reverseJterator& u);

reference operator*() const;

pointer operator->() const;

reverseJterator& operator++();

reverse1terator operator++(1nt);

reverseJterator& operator--();

reversejterator operator--(int);

reverse1terator operator^ (d1fference_type л) const:

reverseJterator& operator+=(d1fference_type n);

reverse_iterator operator- (difference^type n) const;

reverseJ terator& operator-=(differencetype n):

reference operator[](differencetype n) const;

Обратный итератор имеет защищенное поле данных, называемое текущим итера­ тором — current. Операция инкремента реализуется путем декремента этого ите­ ратора:

template reverse_iterator& reverse_1terator operator++(){ Итератор может указывать на все элементы контейнера, включая следующий за последним, но для обратного итератора таким элементом будет элемент, стоящий перед первым, а его не существует. Поэтому current на самом деле указывает на элемент, следующий за тем, на который указывает обратный итератор. Соотно­ шение между прямым и обратным итератором выражается следующим образом:

&*(reverseJterator(i)) == &*(i - 1).

Для обратных итераторов поддерживаются обычные операции отношения =, !=, 0):

valarray shiftdnt 1) const;

// Циклический сдвиг на 1 элементов (влево, если 1>0):

valarray cshiftdnt) const;

// Применение функции func к каждому элементу массива;

valarray apply(Т func(T)) const;

valarray apply(Т func(const T&)) const;

// повторная инициализация (все элементы заменяются на // значение по умолчанию, размер вектора - sz;

void res1ze(s1ze t sz. Т с = T O ) ;

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

Функции сдвига shift и cshlft и применение функции apply возвращают новый массив, при этом исходный остается без изменений. При логическом сдвиге осво­ бодившиеся значения заполняются значением по умолчанию для данного типа элементов.

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

К массивам можно применять функции abs, acos, asin, atari, atan2, cos, cosh, exp, log, loglO, pow, sin, sinh, sqrt, tan, tanh, например:

v2 = cos(v3); / / v 2 [ i ] = cos(v3[i]) для i = 1 Поскольку элементы массива val array представляют собой последовательность, к нему применимы все стандартные алгоритмы и итераторы, рассмотренные в предыдущих разделах. Но более эффективно работать с массивом через срезы и подмножества, рассматриваемые в следующем разделе.

Для val array определены логические операции, ==, != и т. д., дающие в резуль­ тате массив типа bool, каждый элемент которого равен результату операции, при­ мененной к паре соответствующих элементов сравниваемых массивов, например:

tempiate valarray operator== (const valarray&. const valarray&):

tempiate valarray operator!= (const valarray&. const valarray&);

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

Вспомогательные классы Класс si ice (срез) позволяет задать подмножество индексов элементов массива:

class slice{ slice(size_t start. size_t size. size_t stride):

size_t startO const: // индекс первого элемента Шаг — это расстояние между двумя элементами среза. Например, slice(3. 4, 2) задает срез, состоящий из элементов массива с номерами 3, 5, 7, 9, а sliced. 3.

4) — с номерами 1, 5, 9. Таким образом, с помощью срезов можно представить массив как матрицу, задав в нем строку или столбец.

Теперь можно привести пример операции индексации подмножеств массива valarray, описанной в предыдущем разделе: оператор a[slice(l. 5. 3)] = b выпол­ нит присваивание массива b только элементам массива а, заданным срезом.

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

sl1ce_array& si = v2[slice(0, v.slzeO / 10. 10)]:

// Увеличить на 5 первый столбец матрицы 10 X 10:

slice_array& s2 = v2[sl1ce(0, v.sizeO / 10. 1)]:

// Увеличить в 2 раза каждый элемент первой строки матрицы 10 X 10:

В шаблоне si 1се_агray определены сложные операции присваивания (+=, *=, >= и т. д.), например:

void operator*= (const valarray&) const:

void operator/= (const valarray&) const:

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

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

Если требуется работать с подмножеством, которое нельзя задать одним срезом, используется шаблон gslice — обобщенный срез:

class gslice^ gslice(size_t s. const valarray& len.

size_t startO const: // индекс первого элемента valarray sizeO const: // число элементов в измерении valarray strideO const: // шаги для индекса[0]. индекса[1]....

Обобщенный срез задает несколько срезов. Индекс начального элемента ука­ зывается первым параметром s, размеры срезов передаются через массив len, а шаги — через массив d. Размерности массивов, определяющие количество зада­ ваемых срезов, должны совпадать.

Например, если задать параметры получим последовательность индексов массива к = (0.1) X 4 + (0.1.2) X которые дадут в результате матрицу 2x3 из левого верхнего угла матрицы 3x4, расположенной в памяти по столбцам (первый срез с длиной 2 и шагом 4 описыЧасть III. Стандартная библиотека вает два элемента строки, второй — с длиной 3 и шагом 1 — описывает три эле­ мента столбца):

30 Расположение в памяти:

00 10 20 30 01 11 21 31 02 12 Теперь, чтобы, например, обнулить элементы подматрицы 2x3, можно записать:

valarray v ( l. 12); / / Создаем массив из единиц i n t length[] = {2. 3};

valarray len (length. 2);

valarray d (str. 2);

// Обнуляем элементы v[0]. v[l]. v[2]. v[4]. v[5]. v[6]:

v[gslice(0. len. d)] = 0:

Аналогично шаблону si ice_array, для работы с подмножеством элементов масси­ ва, заданным обобщенным срезом, введен шаблон класса gslice_array, содержа­ щий тот же набор элементов, что и slice_array. Самостоятельные объекты класса gslice_array создавать запрещено: все обращения к ним переадресуются на ис­ ходный массив.

Если требуется задать произвольное подмножество элементов массива, для кото­ рого нельзя описать закон изменения индексов, используют логический массив mask^array, который представляет собой valarray. Элемент этого массива, равный true, означает, что соответствующий элемент val array включается в под­ множество. Для mask_array определен тот же набор полей и методов класса, что и для gslice^array.

Объекты этого класса получаются в результате использования в операциях обоб­ щенной индексации val array, описанных в предыдущем разделе, например:

bool m[] = {true. true, false, true, false};

valarray mask (m. 5);

/ / Элементам номер 0. 1 и 2 массива v6 присваивается / / значение синуса соответствующих элементов массива v4.

/ / описанного в предыдущем разделе:

valarray v6 = sin(v4[mask]):

Другой способ выделения произвольного подмножества, позволяющий переупо­ рядочивать элементы val array, является косвенный массив inciirect_array. В нем задается последовательность индексов массива. Объект этого класса создается при использовании в качестве индекса valarray, например:

valarray index(i. 5);

valarray v7 = v4[1nclex];

// v7[0] = v4[3]. v7[l] = v4[2]. v7[2] = v4[4]. v7[3] = v4[0]. v7[4] = v4[l] Число элементов массива, используемого в качестве индекса, не должно превы­ шать число элементов в индексируемом массиве.

Перечисленные классы — sl1ce_array, gsl1ce_array, mask_array и 1ndirect_array — нель­ зя создавать впрямую и копировать. Они прозрачны для пользователя и создают­ ся в результате использования в качестве индекса массива va1 array срезов, обоб­ щенных срезов, логических массивов val array и массивов типа size_t соответственно.

ГЛАВА Другие средства стандартной библиотеки Кроме рассмотренных, стандартная библиотека C++ содержртт средства под­ держки языка, диагностики, локализации, работы с комплексными числами, бо­ лее 200 функций, унаследованных из стандартной библиотеки С, а также типов для их поддержки и макросов.

Средства поддержки языка включают описания функций и типов, которые долж­ ны присутствовать при выполнении программы. Они включают в себя поддерж­ ку запуска и завершения программы, операций new и delete, описание свойств встроенных типов данных, динамическую идентификацию типов, обработку ис­ ключений и другие средства времени выполнения. Эти средства представлены в заголовочных файлах,,,,,, В библиотеке (файл ) определен шаблон класса numer1c_l im1 ts, в котором определяются свойства типа данных, зависяш;ие от реализации: диапазон, точ­ ность, наличие знака и т. д. Для каждого из основных типов данных определена специализация шаблона numeric_l imits. Эти же характеристики определяются и в константах, описанных в заголовочных файлах и, унаследован­ ных из библиотеки С, например:

FLT_DIG — количество верных значаш;их цифр в величине типа float;

F T MN — минимальное нормализованное число с плаваюш;ей точкой, которое может быть представлено типом float;

UN _ A — максимальное значение, которое может принимать величина типа unsigned int (должно быть не менее 65 535).

Полностью эти константы описаны в приложении 5.

Для обработки ошибок при выделении памяти в библиотеке описан класс bad_anoc, тип функций-обработчиков ошибок new_handler и функция установки нового обработчика set_new_handler.

Глава 16. Другие средства стандартной библиотеки Механизм обработки ошибок выделения памяти следующий: если операция new не может выделить требуемое количество динамической памяти, она вызывает функцию-обработчик типа new_hancller, который должен либо попытаться освобо­ дить память, либо породить исключение в виде объекта класса bad_al 1 ос или про­ изводного от него, либо вызвать функцию abort или exit для завершения про­ граммы. Функция set_new_handler используется для установки собственного обработчика вместо стандартного. Как правило, она применяется при перегрузке операций new и delete.

Для поддерэнжи динамической идентификации типов в библиотеке определен класс type_1nfo, рассмотренный в разделе «Преобразования типов» на с. 231, а также классы исключений bad_cast и bad_type1d.

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

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

Ниже кратко описаны эти классы:

• bad_al 1ос — ошибка при динамическом распределении памяти с помощью new;

• bad_cast — неправильное использование оператора dynam1c_cast (см. раздел «Преобразования типов», с. 231);

• bad_type1d — операция typeld не может определить тип операнда (см. с. 238);

• ^bad_exception — порождается, если при вызове функции, в спецификации ис­ ключений которой оно указано, произошло неожидаемое исключение;

• length_error — попытка создания объекта, большего, чем максимальный раз­ мер типа s1ze_t;

• doma1n_error — нарушение внутренних условий перед выполнением действия;

• out_of_range — попытка вызова функции с параметром, не входящим в допус­ тимые значения;

• inval1d_argument — попытка вызова функции с неверным параметром;

• range_error — неправильный результат выполнения;

• overflow_error — арифметическое переполнение (результат слишком большой для указанного типа данных);

• underflow_error — исчезновение порядка (результат слишком маленький для указанного типа данных).

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

Для работы с комплексными числами библиотека предоставляет шаблон класса complex, его специализации для типов float, double и long double, а также много­ численные функции. Все это богатство становится доступным при подключении заголовочного файла.

Функции библиотеки описаны в приложении 6, константы, макросы и типы — в приложении 5, заголовочные файлы — в приложении 4.

Упражнения к части III Стандартные потоки Выполнить задания из раздела «Циклические вычислительные процессы» (см.

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

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

Потоки и типы, определенные пользователем Дополнить программы из раздела «Классы» (см. упражнения ко второй части) перегруженными операциями ввода/вывода в поток для созданных классов.

Строки Выполнить задания из раздела «Функции библиотеки для работы со строками и символами» (см. упражнения к первой части) с использованием класса string.

Контейнерные классы Выполнить задания из разделов «Одномерные и двумерные массивы», «Струк­ туры» и «Динамические структуры данных» (см. упражнения к первой части) с использованием соответствующих контейнерных классов библиотеки.

Алгоритмы Выполнить задания из раздела «Одномерные массивы» (см. упражнения к пер­ вой части) с использованием контейнерных классов и алгоритмов библиотеки.

Класс valarray Выполнить задания из разделов «Одномерные массивы» и «Двумерные масси­ вы» (см. упражнения к первой части) с использованием класса valarray и срезов.

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

Кроме того, как утверждает Скотт Майерс, «работа на C++ при правильном его использовании способна доставить удовольствие». Неполное же понимание функционирования языка, напротив, приводит к созданию программ, полных ошибок и не поддаюш;ихся сопровождению.

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

История создания языка и причины включения в него тех возможностей, которы­ ми он обладает в настоящий момент, подробно описаны в книге Б. Страуструпа «Дизайн и эволюция языка C++» [18]. Изучение этой книги поможет понять, от­ чего средства языка реализованы именно так, а не иначе. Полезные практические советы по грамотному написанию эффективных программ содержатся в книгах [17], [13] и [9]. Для получения полной справочной информации о языке и стан­ дартной библиотеке лучше всего пользоваться стандартом ISO/IEC 14882: (его предварительные варианты, мало отличающиеся от окончательного, можно найти в Интернете).

Желаю всем читателям дальнейших успехов в освоении и использовании C++!

Литература 1. Аммерааль Л. STL для программистов на C++. — М.: ДМК, 2000. — 240 с.

2. Бабэ Б. Просто и ясно о Borland C++. - М.: БИНОМ, 1995. - 400 с.

3. Бадд Т. Объектно-ориентированное профаммирование в действии. — СПб.:

Питер, 1997. - 464 с.

4. Баженова И. Ю. Visual C++ 6.0. Уроки программирования. — М.: ДиалогМИФИ, 1999. - 416 с.

5. Дэвис С. C++ для «чайников». — К.: Диалектика, 1996. — 304 с.

6. Брукс Ф. Мифический человеко-месяц, или как создаются программные ком­ плексы. — М.: «Символ-Плюс», 2000. — 304 с.

7. Буч Г. Объектно-ориентированный анализ и проектирование с примерами на C++.- М.: БИНОМ, 1998. - 560 с.

8. Вирт Н. Алгоритмы + структуры данных = программы. — М.: Мир, 1985. — 9. Голуб А. И. С и C++. Правила программирования. — М.: БИНОМ, 1996. — 10. Карпов Б., Баранова Т. C++: специальный справочник. — СПб.: Питер, 11. Ласло М. Вычислительная геометрия и компьютерная графика на C++. — М.:

БИНОМ, 1997. - 304 с.

12. Луис Д. С и C++. Справочник. — М.: Восточная книжная компания, 1997. — 592 с.

13. Мейерс С. Эффективное использование C++. — М.: ДМК, 2000. — 240 с.

14. Подбельский В, В. Язык Си++: Учебное пособие. — М.: Финансы и статисти­ 15. Пол И. Объектно-ориентированное программирование с использованием C++. - К.: ДиаСофт, 1995. - 480 с.

16. Романовская Л. М. и др. Программирование в среде Си для ПЭВМ ЕС. — М.:

Финансы и статистика, 1992. — 352 с.

17. Страуструп Б. Язык программирования C++. — СПб.: БИНОМ, 1999. — 991 с.

18. Страуструп Б. Дизайн и эволюция языка C++. — М.: ДМК, 2000. — 448 с.

19. Шилдт Г. Теория и практика C++. - СПб.: BHV, 1996. - 416 с.

20. Неформальное введение в С-^+ и Turbo Vision. — Галерея «Петрополь», 1992. — ПРИЛОЖЕНИЕ Операции языка C++ Операции приведены в порядке убывания приоритета. Операции с разными при­ оритетами разделены чертой.

Операция Краткое описание Унарные операции преобразование типа с проверкой на этапе выполнения dynam1c_cast stat1c_cast преобразование типа с проверкой на этапе компиляции reinterpret_cast преобразование типа без проверки const_cast константное преобразование типа -префиксный инкремент Операция унарный плюс delete Бинарные и тернарные операции /Приложение 1. Операции языка C++ Операция Краткое описание остаток отделения с присваиванием -- вычитание с присваиванием «» сдвиг влево с присваиванием »« сдвиг вправо с присваиванием &- поразрядное И с присваиванием поразрядное ИЛИ с присваиванием ^» поразрядное исключающее ИЛИ с присваиванием последовательное вычисление ПРИЛОЖЕНИЕ Спецификации формата для функций семейства printf Спецификация Пояснение аргумент преобразуется к десятичному виду аргумент, рассматриваемый как переменная типа float или double, е,Е преобразуется в десятичную форму в виде [-]m.nnnnnne[+-]xx, где длина строки из п определяется указанной точностью. Точность по 1f аргумент, рассматриваемый как переменная типа float или double, преобразуется в десятичную форму в виде [-]mmm.nnnnn, где длина строки из п определяется указанной точностью. Точность по используется формат %е или ^f, который короче; незначащие нули g,G аргумент преобразуется в беззнаковую восьмеричную форму (без вывод указателя в шестнадцатеричном формате (эта спецификация не входит в стандарт, но она существует практически во всех s аргумент является строкой: символы строки печатаются до тех пор, пока не будет достигнут нулевой символ или не будет напечатано количество символов, указанное в спецификации точности u аргумент преобразуется в беззнаковую десятичную форму аргумент преобразуется в беззнаковую шестнадцатеричную форму 388 Приложение 2. Спецификации формата для функций семейства printf Модификаторы формата Модификаторы формата применяются для управления шириной поля, отво­ димого для^ размещения значения. Модификаторы — это одно или два числа, пер­ вое из которых задает минимальное количество позиций, отводимых под число, а второе — сколько из этих позиций отводится под дробную часть числа (точ­ ность). Если указанного количества позиций для размещения значения недоста­ точно, автоматически выделяется большее количество позиций:

• )l>-minC или ^minC;

• ^-min.precisionC или ^min.precisionC.

Здесь С — специф1/кация формата из приведенной выше таблицы, min — число, задающее минимальную ширину поля. Смысл модификатора precision, также за­ даваемого десятичным числом, зависит от спецификации формата, с которой он используется:

• при выводе строки (спецификация Xs) precision указывает максимальное чис­ ло символов для вывода;

• при выводе вещественного числа (спецификации ^f или *е) precision указы­ вает количество цифр после десятичной точки;

• при выводе целого числа (спецификации Хб или ^i), precision указывает ми­ нимальное количество выводимых цифр. Если число представляется мень­ шим числом цифр, чем указано в precision, выводятся ведущие (начальные) а при выводе вещественного числа (спецификации ^d или XG) precision указы­ вает максимальное количество значащих цифр, которые будут выводится.

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

Перед спецификацией могут использоваться префиксы 1 и h, например, ^1 f, >thu.

Префикс h с типами d, i, о, х и X указывает на то, что тип аргумента short int, а с типом U — short unsigned int.

Префикс 1 с типами d, i, о, х и X указывает на то, что тип аргумента long int, с ти­ пом U - long unsigned int, а с типами е, Е, f, g и G — что тип аргумента double, а не float.

Пример:

#include int main(){ char ch = ' z ', *str = "ramambahari";

p r i n t f C i n t l = ^d| int2 - %3й\ 1nt2 - «-4d|\n". intl. int2. int2) printf ("intl = ^ 1 int2 « ^3x| int2 = Mo|\n". intl. int2. int2);

printfC'f = «fI f « ^4.2f| f - «6.1f|\n". f. f. f);

Приложение 2. Спецификации формата для функций семейства printf printfC'dbl " %b.Z\1\ dbl - ^e| dbl - %^.lG|\n". dbl, dbl, dbl);

printf("ch « %z\ ch = ^3c|\n". ch. ch);

printfC'str -' «14s|\nstr = ^-14s|\nstr = ^S|\n". s t r, s t r, s t r ) ;

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

f = 3.6210001 f - 62 I f = 3. str = ramambahari | ПРИЛОЖЕНИЕ Арифметические преобразования типов Преобразования типов выполняются, если операнды, входящие в выражения, имеют различные типы. Ниже приведена последовательность преобразований.

• Любые операнды типа char, unsigned char или short преобразуются к типу int по правилам:

• char расширяется нулем или знаком в зависимости от умолчания для char;

• unsigned char расширяется нулем;

• signed char расширяется знаком;

• short, unsigned short и enum при преобразовании не изменяются.

ш Затем любые два операнда становятся либо int, либо float, double или long • Если один из операндов имеет тип long double, то другой преобразуется к типу long double.

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

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

• Иначе, если один из операндов имеет тип unsigned long, то другой преобразу­ ется к типу unsigned long.

• Иначе, если один из операндов имеет тип long, то другой преобразуется к типу long.

• Иначе, если один из операндов имеет тип unsigned, то другой преобразуется к типу unsigned.

• Иначе оба операнда должны иметь тип i nt.

Тип результата тот же, что и тип участвующих в выражении операндов.

ПРИЛОЖЕНИЕ Заголовочные файлы стандартной библиотеки Ввод/вывод Функции ввода/вывода в стиле С l Функции для работы с символами Функции ввода/вывода в стиле С для многобайтных символов 1 Базовые классы потоков ввода/вывода Предварительные объявления средств ввода/вывода Стандартные объекты и операции с потоками ввода/вывода 0). Возвращает текущий вид потока.

int fwprintf (FILE *f. const wchar_t *fmt,...);

Функция записывает в поток f переменные, список которых обозначен многото­ чием, в формате, указанном строкой fmt. Возвращает число записанных симво­ лов. Является аналогом функции fprintf для многобайтных символов.

s1ze_t fwriteCconst void *p. size^t size. size_t n. FILE * f ) ;

Функция записывает n элементов длиной size байт из буфера, заданного указате­ лем р, в поток f. Возвращает число записанных элементов.

fwscanf Читает из потока данные и пишет их по заданным адресам int fwscanf (FILE *f. const wchar_t *fmt....);

Функция в соответствии с форматом, указанным строкой fmt, читает из потока f переменные, список адресов которых обозначен многоточием. Возвращает число прочитанных элементов или W O, в случае неудачного чтения. Является анало­ гом функции f scanf для многобайтных символов.

int getc(FILE *f);

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

getchar int getchar(void);

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

getenv int getenv(const char *var_name);

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

char *gets(char *s);

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

getwc wint_t getwc(FILE * f ) ;

Приложение 6. Функции стандартной библиотеки Функция возвращает очередной символ в форме wint^t из потока f. Если символ не может быть прочитан, то возвращается значение W O. Является аналогом функции getc для многобайтных символов.

wint^t getwchar(void);

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

const struct tm *ginti me (const time^t * t ) ;

Функция возвращает указатель на временную структуру типа tm, инициализиро­ ванную на основе даты/времени из t. Время устанавливается по Гринвичу.

isalnum Проверяет, является ли символ буквой или цифрой int isalnum(int ch):

Функция выделяет младший байт параметра ch и возвращает значение true, если символ ch является буквой или цифрой, или false в противном случае.

i n t isalpha(int ch);

Функция выделяет младший байт параметра ch и возвращает значение true, если символ ch является буквой, или f а! зе в противном случае.

1 iscntrl Проверяет, является ли символ управляющим Функция выделяет младший байт параметра ch и возвращает значение true, если символ ch является управляющим символом (типа line feed, del, табуляции и тому подобных, большинство из которых находятся в диапазоне 0x01-ОхIF (для кодировки ASCn)), или false в противном случае.

isdlgit Функция выделяет младший байт параметра ch и возвращает значение true, если символ ch является цифрой, или fal se в противном случае.

int isgraph(int ch):

Функция выделяет младший байт параметра ch и возвращает значение true, если символ ch является видимым (то есть он не является символом пробела, табуля­ ции и т. д.) или false в противном случае.

islower Проверяет, является ли символ буквой нижнего регистра int islowerdnt ch):

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

int ispnnt(int ch):

Функция выделяет младший байт параметра ch и возвращает значение true, если символ ch является печатаемым (isgraph + пробел), или false в противном слу­ чае.

Проверяет, является ли символ символом пунктуации ispunct int ispunct(int ch):

Функция выделяет младший байт параметра ch и возвращает значение true, если символ ch является символом пунктуации (то есть печатаемым, но не буквой, не цифрой, не пробелом), или false в противном случае.

isspace int isspace(int ch):

Функция выделяет младший байт параметра ch и возвращает значение true, если символ ch является символом пробела или табуляцией, или символом новой строки, или символом новрй страницы (символом перевода формата), или false в противном случае.

Проверяет, является ли символ буквой верхнего регистра isupper int isupperCint ch):

Функция выделяет младший байт параметра ch и возвращает значение true, если символ ch является буквой верхнего регистра, или false в противном случае.

1 iswalnum Проверяет, является ли символ буквой или цифрой int iswalnum(wint_t ch):

Функция возвращает значение true, если символ ch является буквой или циф­ рой, или false в противном случае. Является аналогом функции isalnum для мно­ гобайтных символов.

Приложение 6. Функции стандартной библиотеки int iswalpha(w1nt_t ch);

Функция возвращает значение true, если символ ch является буквой, или false в противном случае. Является аналогом функции isalpha для многобайтных сим­ волов.

iswcntrl Проверяет, является ли символ управляющим int iswcntrl(wint_t ch):

Функция возвращает значение true, если символ ch является управляющим сим­ волом (типа line feed, del, табуляции и тому подобных, большинство из которых находятся в диапазоне OxOl-OxlF (для кодировки ASCH)), или false в против­ ном случае. Является аналогом функции iscntrl для многобайтных символов.

i swctype int iswctype(wint_t с. wctype_t desc):

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

1 iswdigit int iswdigit(wint_t ch):

Функция возвращает значение true, если символ ch является цифрой, или false в противном случае. Является аналогом функции isdigit для многобайтных сим­ волов.

iswgraph Проверяет, является ли символ видимым int iswgraph(wint_t ch):

Функция возвращает значение true, если символ ch является видимым (то есть он не является символом пробела, табуляции и т. д.) или false в противном слу­ чае. Является аналогом функции isgraph для многобайтных символов.

iswlower Проверяет, является ли символ буквой нижнего регистра int iswlower(wintt ch):

Функция возвращает значение true, если символ ch является буквой нижнего ре­ гистра, или false в противном случае. Является аналогом функции islower для многобайтных символов.

I iswprint int iswprint(wint_t ch):

Функция возвращает значение true, если символ ch является печатаемым (iswgraph + пробел), или false в противном случае. Является аналогом функции iswprint для многобайтных символов.

iswpunct Проверяет, является ли символ символом пунктуации int iswpunct(w1nt_t ch);

Функция возвращает значение true, если символ ch является символом пунктуа­ ции (то есть печатаемым, но не буквой, не цифрой, не пробелом), или false в про­ тивном случае. Является аналогом функции Ispunct для многобайтных символов.

Проверяет, является ли символ разграничительным int iswspace(wintt ch);

Функция возвращает значение true, если символ ch является символом пробела или табуляцией, или символом новой строки, или символом новой страницы (символом перевода формата), или false в противном случае. Является аналогом функции isspace для многобайтных символов.

iswupper Проверяет, является ли символ буквой верхнего регистра int iswupper(wintt ch);

Функция возвращает значение true, если символ ch является буквой верхнего ре­ гистра, или false в противном слз^ае. Является аналогом функции isupper для многобайтных символов.

iswxdigit int iswxdigit(wintt ch);

Функция возвращает значение true, если символ ch является символом шестнад­ цатеричной цифры (цифры, а также буквы от А до F в нижнем или верхнем реги­ страх), или false в противном случае. Является аналогом функции isxdigit для многобайтных символов.

j Isxdigit int isxdigit(int ch);

Функция выделяет младший байт параметра ch и возвращает значение true, если символ ch является символом шестнадцатеричной цифры (цифры, а также букЪы от А до F в нижнем или верхнем регистрах), или false в противном случае.

long int labsClong int num);

Приложение 6. Функции стандартной библиотеки Функция возвращает абсолютное значение числа num.

Idexp Преобразует мантиссу и показатель степени ц число double ldexp(double х, 1nt exp):

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

ld1vt Idivdong numerator, long denominator):

Функция делит длинное целое numerator на длинное целое denominator, возвращая результат в структуре, содержащей частное и остаток.

localeconv Возвращает описание установок локальной среды struct Iconv *localeconv(void);

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

localtime struct tm localtime(timet * t ) :

Функция возвращает указатель на временную структуру типа tm, инициализиро­ ванную на основе даты/времени из t. Время устанавливается локальное (в отли­ чие от gmtime,,гдe время устанавливается по Гринвичу).

double log(double х);

Функция возвращает значение натурального логарифма х.

loglO double loglOCdouble х);

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

mall ос void *malloc(size_t size);

Функция выделяет блок памяти размером size байт и возвращает указатель на него. В случае неудачи возвращаемым значением будет N L. Предпочтительней вместо та 11 ос использовать операцию new.

int mblen(const char *s. s1ze_t n):

Функция возвращает размер символа *s, если s не N L.

sizet mbstowcs(wchar_t *pwcs. const char * s. sl2et n ) ;

Функция преобразует строку многобайтных символов в массив из wchar^t. Если встретился недопустимый символ, функция возращает - 1. В противном случае функция возвращает количество преобразованных символов.

mbtowc i n t mbtowc(wchar_t *pwc. const char * s. sizet n ) :

Функция преобразует многобайтный символ в wchar^t. Если s указывает на немногобайтный символ, функция возращает - 1. Если s указывает на N L, возвра­ щаемое значение равно 0. В противном случае функция возвращает длину сим­ вола в байтах.

memchr Ищет первое вхождение символа в блок памяти void *memchr(const void * p. i n t ch. size^t n ) :

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

memcmp i n t memcmpCconst void * p l. const void *p2. sizet n ) ;

Функция сравнивает два блока памяти и возвращает значение: меньше нуля, рав­ ное нулю или больше нуля — аналогично кодам возврата функции strcmp.

memcpy void *memcpy(void *dest. const void *src. sizet n):

Функция копирует блок памяти длиной п байт из адреса src по адресу dest.

memmove void *memmove( void *dest. const void *src. size^t n):

Функция аналогична memcpy, но блоки dest и src могут перекрываться.

Приложение 6. Функции стандартной библиотеки void *memset(const void *p. 1nt ch. size^t n);

Функция заполняет блок памяти символом, взятым из младшего байта ch.

struct tm mktime(time_t *t);

Функция заполняет поля дня недели и дня года структуры tm на основе имею­ щейся в t информации.

double modf(double x. double *intptr):

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

реггог Печатает строку вида "s: error сообщение" void perror(const char *s);

Функция печатает строку вида «s: error сообщение», в которой сообщение опре­ деляется на основе значения глобальной переменной еггпо. Если значением s яв­ ляется N L, то печатается только сообщение об ошибке. Вывод производится в стандартный поток ошибок stderr, обычно назначенный на монитор.

double powCdouble x. double y):

Функция вычисляет значение числа х в степени у.

Выводит строку параметров в определенном формате printf int printf (const char *fmt....);

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

int putc(int ch. FILE * f ) :

Функция записывает символ ch в поток f. При ошибке возвращает значение EOF, иначе — записанный символ. Работает полностью аналогично fputc.

putchar Выводит символ на стандартное устройство вывода 1nt putchardnt ch):

Функция выводит символ ch на стандартное устройство вывода. Если вывод ус­ пешен, возвращается значение ch, иначе возвращается значение EOF.

1nt puts(char *s);

Функция выводит строку S на стандартное устройство вывода, добавляя в конце символ новой строки. Возвращает неотрицательное значение при успехе или E F — при ошибке.

putwc wint^t putwc(wint_t ch. FILE * f ) :

Функция записывает символ ch в поток f. При ошибке возвращает значение W O, иначе — записанный символ. Является аналогом функции putc для многобайт­ ных символов.

1 putwchar Выводит символ на стандартное устройство вывода wintt putwchar(wint_t ch):

Функция выводит символ ch на стандартное устройство вывода. Если вывод ус­ пешен, возвращается значение ch, иначе возвращается значение W O. Является аналогом функции putchar для многобайтных символов.

qsort void qsort(void *buf. size^t num. size^t size, int (compare)(const void *. const void * ) ) :

Функция выполняет сортировку массивов любых размеров и типов. Сортируе­ мый массив: buf — указатель на массив, num -- число элементов, si ze — размер ка­ ждого элемента. Аргумент compare — адрес функции, которая должна сравнить два значения, переданных ей функцией qsort, и возвратить соответствующий код: меньше нуля (если первый аргумент меньше второго), нуль (если аргументы равны) или больше нуля (если первый аргумент больше второго). Аргументы, передаваемые ей, определены как void*, то есть внутри функции они должны приводиться к нужному типу.

raise int raise(int signal):

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

i n t rand(vold);

Функция возвращает очередное псевдослучайное число в диапазоне от О до RAND МАХ.

real 1 ос Изменяет размеры ранее выделенного блока памяти void *realloc(vo1d ^memblock. size_t size);

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

Большинство правил, относящихся к mall ос, действительны и для real 1 ос.

Значение, возвращаемое функцией, является указателем на новое положение блока памяти. Оно отличается от старого значения (memblock) только в том слу­ чае, если real 1 ос пришлось переместить блок памяти. Если не удалось увеличить блок памяти, то возвращаемое значение равно N L, причем значение memblock остается доступным программе.

remove 1nt remove(const char ^filename):

Функция удаляет существующий файл. В случае успеха возвращает нулевое зна­ чение, иначе — ненулевое.

rename 1nt rename(const char *oldname. const char ^newname):

Функция переименовывает существующий файл или папку. В случае успеха воз­ вращает нулевое значение, иначе — ненулевое.

Очищает флаги ошибок при работе с потоком и переходит rewind void rew1nd(FILE *f):

Функция очищает флаги ошибок в потоке f и устанавливает текущую позицию на начало файла.

scanf Вводит строку параметров в определенном формате int scanfCconst char *fmt [. p a r i. par2....]);

Функция вводит строку параметров pari, раг2 и т. д. в формате, определенном строкой fmt, со стандартного устройства ввода (обычно с клавиатуры). Возвра­ щает число переменных, которым присвоено значение.

void setbuf(FILE *f. char *p):

Функция устанавливает буфер ввода/вывода, заданный указателем р. Размер бу­ фера должен быть длиной BUFSIZ. Если р равен nul 1, то буферизация отменяется.

setlocale char *setlocale(1nt type, const char ^locale);

Функция устанавливает новую локализацию программы.

setvbuf void setvbuf (FILE *f. char '^p. i n t mode, s1ze_t size);

Функция устанавливает буфер ввода/вывода, заданный указателем р. Параметр mode указывает режим, а size — размер буфера. Возвращается значение О при успешном завершении и ненулевое значение в случае ошибки. Параметр mode яв­ ляется целым, принимающим одно из значений: _IOFBF (полная буферизация), _IONBF (запрет буферизации) и _IOLBF (для вывода — построчная буферизация, то есть опустошение буфера при записи в буфер символа новой строки).

signal void (^signaKint signum. void ( * f u n c ) ( i n t ) ) ) ( i n t ) :

Функция регистрирует обработчик сигналов. Несмотря на то, что обработчики исключений C++ обеспечивают лучший механизм управления ошибками, функ­ ции signal и raise включены в библиотеку для совместимости с С.

double sin(double x);

Функция возвращает значение синуса угла, равного х радиан.

double sinh(double x);

Функция возвращает значение гиперболического синуса угла, равного х радиан.

Если значение функщш окажется вне представимого диапазона, то функция воз­ вращает значение H G V L а глобальная переменная еггпо получает значение ERANGE.

Выводит строку параметров в определсппом формате sprintf int sprintfCchar ^buffer, const char *format[. argument.... ] ) ;

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

double sqrt(doub1e х);

Функция возвращает квадратный корень из числа х.

srand Устанавливает начальное псевдослучайное число void srand(uns1gned 1nt seed);

Функция устанавливает начальное значение последовательности псевдослучай­ ных чисел.

int sscanf(const char *buf. const char *format [.pari. par2....]):

Функция аналогично функции scanf вводит данные, но не с клавиатуры, а из строки символов, переданной ей первым параметром. Аргумент buf — строка символов, из которой вводятся значения, format — строка формата, в соответст­ вии с которой происходит преобразование данных, а многоточие указывает на наличие необязательных аргументов, соответствующих адресам вводимых значе­ ний.

char '^strcatCchar *sl. char *s2);

Функция добавляет s2 к si и возвращает si. В конец результирующей строки до­ бавляется нуль-символ.

char *strchr(char *s. int ch):

Функция возвращает указатель на первое вхождение символа ch в строку s, если его нет, то возвращается N L.

int *strcmp(char * s l. char *s2);

Функция сравнивает строки и возвращает отрицательное (если si меньше s2), нулевое (если si равно s2) или положительное (если si больше s2) значение.

strcoll Сравнивает строки с учетом установленной локализации char *strcoll(char * s l. char *s2);

Функция сравнивает строки аналогично strcmp, но учитывает установки локали­ зации (см. функцию set!оса 1е).

char *strcpy(char *sl. char ^^$2);

Функция копирует s2 в si и возвращает si.

size_t"strcspn(char *sl. char *s2):

Функция возвращает значение индекса любого из символов из s2 в строке si.

strerror Возвращает указатель па строку с описанием ошибки char * strerror(s1ze_t n):

Функция возвращает указатель на строку с описанием ошибки номер п.

strftime struct tm strft1me(char *s.s1ze_t size. fmt. const struct tm *ctm);

Функция возвращает отформатированную строку с датой и временем на основе формата fmt. Значение функции имеет тип time_t, соответствующий типу tm.

strlen s1ze_t strlen(char *s);

Функция возвращает длину строки (без учета символа завершения строки).

strncat char *strncat(char * s l. char *s2. s1ze_t n);

Функция добавляет не более л символов из s2 к si и возвращает si. Первый сим­ вол s2 пишется на место завершающего нуль-символа строки si. Если длина строки s2 меньше л, переписываются все символы s2. К строке si добавляется нуль-символ. Если строки перекрываются, поведение не определено.

strncmp Сравнивает одну строку с п символами другой 1лt strлcmp(char '^sl. char *s2. s1ze_t л):

Приложение 6. Функции стандартной библиотеки Функция сравнивает первую строку и первые п символов второй строки и воз­ вращает отрицательное (если si меньше s2), нулевое (если si равно s2) или поло­ жительное (если si больше s2) значение.

strncpy Копирует первые п символов одной строки в другую char ^strncpy(char '^sl. char *s2. s1ze_t n):

Функция копирует не более n символов из s2 в si и возвращает si. Если длина исходной строки превышает или равна п, нуль-символ в конец строки si не до­ бавляется. В противном случае строка дополняется нуль-символами до п-го сим­ вола. Если строки перекрываются, поведение не определено.

char *strpbrk(char * s l. char '^s2);

Функция возвращает указатель на символ, являющийся первым вхождением лю­ бого из символов из s2 в строку si, если его нет, возвращается N L.

char *strrchr(char * s. i n t ch):

Функция возвращает указатель на первое вхождение символа ch в строку s спра­ ва, если его нет, возвращает N L.

Ищет символ одной строки, отсутствующий в другой strspn size_t strspnCchar *sl. char *s2);

Функция возвращает индекс первого символа в si, отсутствующего в s2.

strstr char *strstr(char * s l. char *s2);

Функция выполняет поиск первого вхождения подстроки s2 в строку si. В слу­ чае удачного поиска, возвращает указатель на элемент из si, с которого начинает­ ся s2, и N L в противном случае.

strtod double strtocKconst char * s t r. char **encl):

Функция преобразует строку символов в числовое значение и возвращает его.

При переполнении возвращает +/-HUGE_VAL. При невозможности выполнить пре­ образование или исчезновении порядка возвращает 0. В обоих последних случа­ ях еггпо устанавливается в E A G. end указывает на символ, на котором преобра­ зование завершается.

char *strtok(char * s l. char *s2):

Функция возвращает следующую лексему из si, отделенную любым из символов из набора s2.

Преобразует строку в число с учетом системы счисления double strtol(const char *str. char **end. 1nt radix);

Функция преобразует строку символов в числовое значение с учетом указанной системы счисления radix и возвращает полученное число. Функция пропускает возможные начальные пробелы и заканчивает преобразование на первом симво­ ле, который не может появиться в образе числа. Параметр end является адресом указателя типа char*; этот указатель будет содержать адрес первого непреобразованного символа.

При переполнении возвращает L N _ A или L N _ I. При невозможности вы­

O GM X O G MN

полнить преобразование возвращает 0. В обоих последних случаях errno устанав­ ливается в ERAN6E.

strtoul double strtoul(const char *str. char **end. int radix);

Функция работает аналогично strtol, но работает с беззнаковым длинным це­ лым. При переполнении возвращает U O GM X Преобразует строки на основе текущей локализации strxfrm size_t strxfrm(char * s l. char *s2. size_t n);

Функция преобразует строку из s2 и помещение ее в si на основе текущей лока­ лизации. Преобразуется не более п символов.

Выводит строку параметров в определенном формате swprintf int swprintf(wchart ^buffer, const wchar_t *format[. argument....]):

Функция выводит в строку buffer значения переменных, перечисленных в спи­ ске, обозначенном многоточием, в формате, определенном строкой format. Явля­ ется аналогом функции sprintf для многобайтных символов.

swscanf int swscanf(const wchar_t *buf. const wchar_t ^format.. J ;

Функция аналогично функции scanf вводит данные, но не с клавиатуры, а из строки символов, переданной ей первым параметром. Аргумент buf — строка символов, из которой вводятся значения, format — строка формата, в соответстприложение 6. Функции стандартной библиотеки В И с которой происходит преобразование данных, а многоточие указывает на наличие необязательных аргументов, соответствующих адресам вводимых значе­ ний. Является аналогом функции sscanf для многобайтных символов.

system Передает строку командному процессору ОС 1nt systemCconst char ^command);

Функция передает строку командному процессору операционной системы. Это позволяет исполнить другую программу или утилиту. Возвращаемое значение зависит от реализации, но, как правило, значение О указывает на успешное завер­ шение.

double tan(double x);

Функция возвращает значение тангенса аргумента х.

tanh Возвращает гиперболический тапгепс аргумента double tanh(double х);

Функция возвращает значение гиперболического тангенса аргумента х.

t1me_t t1fTie(t1me_t * t ) ;

Функция возвращает текущие дату/время в виде time^t (количество секунд, про­ шедших с полуночи 1 января 1970 года). Если *t не равно N L, то значение зано­ сится и по этому адресу.

tmpfile Открывает поток двоичного ввода/вывода FILE nmpfile(vold);

Функция открывает временный файл в режиме двоичного ввода/вывода и воз­ вращает указатель на поток.

char 4mpnam(char * s ) ;

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

Т РМ Х определена в и равна 65535. Параметр s - либо О, либо указатель на массив, состоящий не менее, чем из L^tmpnam символов. L_tmpnam определено в. Если s — ноль, tmpnam оставляет имя генерированного временного фай­ ла во внутреннем статическом объекте и возвращает указатель на этот объект.

Если S не ноль, tmpnam помещает свой результат в указанный массив, который должен быть длиной не менее L_tmpnam символов, и возвращает s.

1nt tolowerdnt ch);

Функция получает параметр ch и возвращает его в нижнем регистре. В параметре ch используется только младший байт.

i n t toupperdnt ch);

Функция получает параметр ch и возвращает его в верхнем регистре. В парамет­ ре ch используется только младший байт.

1nt tolower(w1nt_t ch);

Функция получает символ ch и возвращает его в нижнем регистре. Является ана­ логом функции tolower для многобайтных символов.

int towupper(w1nt_t ch);

Функция получает символ ch и возвращает его в верхнем регистре. Является ана­ логом функции toupper для многобайтных символов.

ungetc i n t ungetcCint ch. FILE * f ) ;

Функция возвращает символ ch обратно во входной поток f. Возвращает EOF в случае ошибки, в противном случае возвращает ch. Гарантируется возвращение только одного символа.

ungetwc wint_t ungetwc(wint_t ch. FILE * f ) ;

Функция возвращает символ ch обратно во входной поток f. Возвращает WO EF в случае ошибки, в противном случае возвращает ch. Гарантируется возвращение только одного символа. Является аналогом функции ungetc для многобайтных символов.

vfprintf int vfprintf(FILE ^stream, char ^format. va_list a r g l i s t ) ;

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

i n t vfwprintf (FILE ^stream, wchar^t ^format, v a j i s t a r g l i s t ) ;



Pages:     | 1 | 2 || 4 |


Похожие работы:

«Государственное образовательное учреждение высшего профессионального образования Елецкий государственный университет им. И.А. Бунина Центр свободного программного обеспечения Материалы Всероссийской научно­практической конференции с международным участием   Информационные технологии  на базе свободного программного  обеспечения    21 мая 2010 г.    Елец  УДК [681/3:Ч30/49](063) ББК 32.81+32.97  И 74 Печатается по решению редакционно­издательского совета...»

«1 ЦЕЛИ И ЗАДАЧИ КУРСА Государство и право – важнейшие факторы общественной эволюции, непременные спутники современного общества, принадлежащие к числу не только наиболее важных, но и наиболее сложных общественных явлений. Курс Основы государства и права одна из дисциплин, изучаемых студентами неюридических факультетов в соответствии с требованиями Государственных образовательных стандартов высшего профессионального образования. Цель изучения дисциплины - дать студентам необходимые знания об...»

«Алгоритмы и программные средства решения вычислительных задач тропической математики Губанов Сергей Александрович, гр. 522 Санкт-Петербургский государственный университет Математико-механический факультет Кафедра статистического моделирования Научный руководитель: д.ф.-м.н., доцент Кривулин Н.К. Рецензент: к.ф.-м.н., доцент Христинич В.Б. Санкт-Петербург 2012г. 1/17 Губанов Сергей Александрович, гр. 522 Вычислительные задачи тропической математики Введение Введение Введение Идемпотентная...»

«Муниципальное бюджетное общеобразовательное учреждение Средняя общеобразовательная школа №57с углубленным изучением английского языка г. Владивостока Принято Согласовано Утверждаю Руководитель МО Заместитель директора по Директор МБОУ СОШ №57 начальных классов МБОУ учебной работе МБОУ Круглова Г.В СОШ №57 Александрова СОШ №57 Приказ № 160\10 от 31.08.13 МА Могилевкина Е.М. Протокол №1 от 29.08.2013 Дата 30.08.2013 РАБОЧАЯ ПРОГРАММА ПО ПРЕДМЕТУ Физическая культура 3 КЛАСС На 2013/14 учебный год...»

«ПРОГРАММА ЭКЗАМЕНА История и теория христианского искусства для поступления в магистратуру факультета Церковных художеств по направлению 035400 История искусств программа подготовки История и теория христианского искусства Программа 1-го вопроса билета ИКОНОВЕДЕНИЕ И ИКОНОГРАФИЯ 1. Происхождение церковного искусства, его литургические основы. Православный и протестантский взгляды на этот вопрос. Библейские основы иконопочитания по Ветхому Завету. Предпосылки иконопочитания в Новом Завете. 2....»

«СОДЕРЖАНИЕ 1. Общие положения 1.1. Основная образовательная программа высшего профессионального образования (ООП ВПО) магистратуры, реализуемая вузом по направлению подготовки 020400.68 – Биология (магистерская программа Физиология человека и животных). 1.2. Нормативные документы для разработки ООП магистерской программы Физиология человека и животных 1.3. Общая характеристика магистерской программы Физиология человека и животных 1.4 Требования к уровню подготовки, необходимому для освоения...»

«1. ОБЩИЕ ПОЛОЖЕНИЯ Настоящая рабочая программа по Проектированию продукции общественного питания разработана в соответствии с государственным образовательным стандартом высшего профессионального образования по направлению 65700 Технология продовольственных продуктов специального назначения и общественного питания. Одна из задач профессиональной деятельности выпускника – проектная деятельность (анализ и поиск наиболее обоснованных проектных решений в условиях многокритериальности и...»

«РАБОЧАЯ ПРОГРАММА ПРОФЕССИОНАЛЬНОГО МОДУЛЯ Приготовление блюд из рыбы 2011 г. 1 Рабочая программа профессионального модуля разработана на основе Федерального государственного образовательного стандарта по специальностям начального профессионального образования (далее – НПО) 260807.01 Повар, кондитер. Организация-разработчик: ГБОУ СПО Комаричский механико-технологический техникум п. Комаричи Разработчик Лысенко Е.Н. ГБОУ СПО Комаричский механико-технологический техникум п. Комаричи Рекомендована...»

«ПРИМЕРНАЯ ПРОГРАММА УЧЕБНОЙ ДИСЦИПЛИНЫ Иностранный язык (английский) 2010г. Примерная программа учебной дисциплины разработана на основе Федерального государственного образовательного стандарта (далее – ФГОС) по специальности среднего профессионального (специальностям) образования (далее - СПО) / профессии (профессиям) начального профессионального образования (далее - НПО) 110809 Механизации сельского хозяйства. Организация-разработчик: ГОУ СПО КРК Интеграл Разработчики: Помазанова Е.В.,...»

«РОССИЙСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ НЕФТИ И ГАЗА ИМЕНИ И.М. ГУБКИНА Факультет экономики и управления УТВЕРЖДАЮ Декан факультета экономики и управления, д.э.н., профессор Андреев А.Ф. 21 февраля 2012 г. ПРОГРАММА вступительных испытаний при поступлении в магистратуру по направлению 080200 Менеджмент Магистерские программы: • Управление проектами • Финансовый менеджмент • Управление персоналом • Международный бизнес • Управление инновационными процессами на предприятиях нефтегазовой...»

«Министерство образования и науки Российской Федерации Беловский институт (филиал) федерального государственного бюджетного образовательного учреждения высшего профессионального образования Кемеровский государственный университет кафедра общественных наук Рабочая программа дисциплины Особенности российского федерализма Направление подготовки 030900.62 Юриспруденция Квалификация (степень) выпускника Бакалавр Форма обучения заочная Белово Print to PDF without this message by purchasing novaPDF...»

«Министерство образования и науки Российской Федерации Федеральное государственное бюджетное образовательное учреждение высшего профессионального образования ОМСКИЙ ГОСУДАРСТВЕННЫЙ ТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ Принята Утверждаю решением Ученого совета Ректор ОмГТУ университета _ В.В. Шалай (протокол № 2013 г. от 2013 г. Основная образовательная программа высшего профессионального образования направления подготовки бакалавриата 261700.62 Технология полиграфического и упаковочного производства Профили...»

«Министерство образования и науки Российской Федерации ПРОГРАММА-МИНИМУМ кандидатского экзамена по специальности 05.13.12 Системы автоматизации проектирования по физико-математическим и техническим наукам Программа-минимум содержит 11 стр. 2007 2 Введение В основу настоящей программы положены следующие дисциплины: Автоматизация проектирования систем, Системное программное обеспечение, Алгоритмические языки и программирование, Операционные системы, Моделирование систем, Экспертные системы....»

«М инист ерст во образования и науки Аст раханской област и Г АО У АО В ПО А с т р а ха н с к и й и н ж е н е р н о - с т р о и т е л ь н ы й и н с т и т у т УТВЕРЖДАЮ Первый проректор Золина Т.В._ _ _2013 г. РАБОЧАЯ ПРОГРАММА Наименование дисциплины Отделочные материалы и композиция По направлению подготовки 270300 Дизайн архитектурной среды Проектирование городской среды По профилю подготовки Кафедра ДРР Квалификация (степень) выпускника бакалавр Астрахань — Разработчики: Ст. преподаватель...»

«Заслушано Утверждаю на заседании МО Директор ГБОУ СОШ №1738 Председатель МО имени авиаконструктора М.Л.Миля _( Афонина АА ) (Николаевская ВС ) 25 августа 2014 г. 25 августа 2014 г. Рабочая учебная программа базового курса 10-11 классов для 10-11 классов по английскому языку ГБОУ СОШ №1738 имени авиаконструктора М.Л.Миля Статус класса общеобразовательный Количество часов 102 (3ч в нед.) Уровень базовый Контрольных работ: 11А- Составлена на основе программы ( авторы)_Альпаков В.Г. Программа...»

«Министерство финансов Российской Федерации Министерство финансов Республики Карелия Редакция журнала Финансы Редакция журнала Бюджет Петрозаводский государственный университет ПРОБЛЕМЫ СОВЕРШЕНСТВОВАНИЯ БЮДЖЕТНОЙ ПОЛИТИКИ РЕГИОНОВ И МУНИЦИПАЛИТЕТОВ Труды Десятой научно-практической конференции (28–30 сентября 2011 г.) Финансовая поддержка Информационная поддержка Петрозаводск Издательство ПетрГУ 2011 ББК 65.9 (2Р) 26 + 65.9 (4) П781 УДК 338 (470) Редакционная коллегия: кандидат экономических...»

«Пояснительная записка Данная Рабочая программа по Окружающему миру для 2 класса первой ступени образования составлена с использованием нормативно-правовой базы: Закон Российской Федерации Об образовании (статья 7, 9, 32); Федеральный государственный образовательный стандарт начального общего образования (приказы Министерства образования и науки Российской Федерации от 06.10.2009 № 373 (зарегистрировано в Минюсте России 22.12.2009, регистрационный номер 19785) Об утверждении и введении в...»

«2 Содержание 1. Основная профессиональная образовательная программа подготовки специалиста, реализуемая вузом по специальности 080507.65 – Менеджмент организации..3 1.1. Нормативные документы для разработки ОПОП по специальности Менеджмент организации. 1.2. Общая характеристика вузовской основной профессиональной образовательной программы высшего образования 1.3. Требования к уровню подготовки абитуриента 2 Характеристика профессиональной деятельности 2.1 Область профессиональной деятельности...»

«Министерство образования Российской Федерации Российский химико-технологический университет им. Д. И. Менделеева ОСНОВЫ МАТЕРИАЛОВЕДЕНИЯ. УКАЗАНИЯ К ИЗУЧЕНИЮ КУРСА Москва 2002 Составители: Г. М. Семенов., А. С. Федосеев, В. Б. Сажин. 2 nгл=ле.,е bеде.,е..3 1. Рекомендуемые темы курсовых работ. 6 2. Вопросы к коллоквиумам..11 2.1 Коллоквиум №1..11 2.2 Коллоквиум №2..13 2.3 Коллоквиум №3..14 3 Примеры заданий контрольных работ.15 3.1 Контрольная работа №1..16 3.2 Контрольная работа №2.. 3.3...»

«Мягкая А.В. Myagkaya A.V. соискатель Ставропольского post-graduate student of государственного университета, Stavropol State University, г. Изобильный Izobilniy БЮДЖЕТИРОВАНИЕ BUDGETING В ТОРГОВЫХ ОРГАНИЗАЦИЯХ IN TRADE ORGANIZATIONS Аннотация: The summary: Автором проводится анализ различных ме- The author analyzes different methods for тодов расчета и ведения бюджета в торго- calculating and maintaining the budget in trade вых организациях. organizations. Ключевые слова: Keywords:...»






 
2014 www.av.disus.ru - «Бесплатная электронная библиотека - Авторефераты, Диссертации, Монографии, Программы»

Материалы этого сайта размещены для ознакомления, все права принадлежат их авторам.
Если Вы не согласны с тем, что Ваш материал размещён на этом сайте, пожалуйста, напишите нам, мы в течении 1-2 рабочих дней удалим его.