С.Б. Липпман, Ж. Лажойе - Язык программирования С++ Вводный курс (1114944), страница 6
Текст из файла (страница 6)
Каждый объект инициализирован константой – целым числом 10,вещественным числом 19.99, символом пробела и логическим значением false.Между основными типами данных может осуществляться неявное преобразование типов.Если переменной age, имеющей тип int, присвоить константу типа double, например:age = 33.333;то значением переменной age станет целое число 33. (Стандартные преобразованиятипов, а также общие проблемы преобразования типов рассматриваются в разделе 4.14.)Стандартная библиотека С++ расширяет базовый набор типов, добавляя к ним такие// заголовочный файл с определением типа string#include <string>string current_chapter = "Начинаем";// заголовочный файл с определением типа vector#include <vector>типы, как строка, комплексное число, вектор, список.
Примеры:vector<string> chapter_titles(20);Здесь current_chapter – объект типа string, инициализированный константой"Начинаем". Переменная chapter_titles – вектор из 20 элементов строкового типа.Несколько необычный синтаксис выраженияvector<string>сообщает компилятору о необходимости создать вектор, содержащий объекты типаstring. Для того чтобы определить вектор из 20 целых значений, необходимо написать:vector<int> ivec(20);Никакой язык, никакие стандартные библиотеки не способны обеспечить нас всемитипами данных, которые могут потребоваться.
Взамен современные языкипрограммирования предоставляют механизм создания новых типов данных. В С++ дляэтого служит механизм классов. Все расширенные типы данных из стандартнойбиблиотеки С++, такие как строка, комплексное число, вектор, список, являютсяклассами, написанными на С++. Классами являются и объекты из библиотекиввода/вывода.Механизм классов – одна из самых главных особенностей языка С++, и в главе 2 мырассмотрим его очень подробно.1.2.1. Порядок выполнения инструкцийПо умолчанию инструкции программы выполняются одна за другой, последовательно. Впрограмме19С++ для начинающихint main(){readIn();sort();compact();print();return 0;}первой будет выполнена инструкция readIn(), за ней sort(), compact() и наконецprint().Однако представим себе ситуацию, когда количество продаж невелико: оно равно 1 илидаже 0.
Вряд ли стоит вызывать функции sort() и compact() для такого случая. Новывести результат все-таки нужно, поэтому функцию print() следует вызывать в любомслучае. Для этого случая мы можем использовать условную инструкцию if. Нам придетсяпереписать функцию readIn() так, чтобы она возвращала количество прочитанных// readIn() возвращает количество прочитанных записей// возвращаемое значение имеет тип intint readIn() { ...
}// ...int main(){int count = readIn();// если количество записей больше 1,// то вызвать sort() и compact()if ( count > 1 ) {sort();compact();}if ( count == 0 )cout << "Продаж не было\n";elseprint();return 0;записей:}Первая инструкция if обеспечивает условное выполнение блока программы: функцииsort() и compact() вызываются только в том случае, если count больше 1.
Согласновторой инструкции if на терминал выводится сообщение “Продаж не было”, еслиусловие истинно, т.е. значение count равно 0. Если же это условие ложно, производитсявызов функции print(). (Детальное описание инструкции if приводится в разделе 5.3.)Другим распространенным способом непоследовательного выполнения программыявляется итерация, или инструкция цикла. Такая инструкция предписывает повторять20С++ для начинающихблок программы до тех пор, пока некоторое условие не изменится с true на false.int main(){int iterations = 0;bool continue_loop = true;while ( continue_loop != false ){iterations++;cout << "Цикл был выполнен " << iterations << "раз\n";if ( iterations == 5 )continue_loop = false;}return 0;Например:}В этом надуманном примере цикл while выполняется пять раз, до тех пор покапеременная iterations не получит значение 5 и переменная continue_loop не станетравной false.
Инструкцияiterations++;увеличивает значение переменной iterations на единицу. (Инструкции цикла детальнорассматриваются в главе 5.)1.3. Директивы препроцессораЗаголовочные файлы включаются в текст программы с помощью директивыпрепроцессора #include. Директивы препроцессора начинаются со знака “диез” (#),который должен быть самым первым символом строки.
Программа, котораяобрабатывает эти директивы, называется препроцессором (в современных компиляторахпрепроцессор обычно является частью самого компилятора).Директива #include включает в программу содержимое указанного файла. Имя файла#include <some_file.h>может быть указано двумя способами:#include "my_file.h"Если имя файла заключено в угловые скобки (<>), считается, что нам нужен некийстандартный заголовочный файл, и компилятор ищет этот файл в предопределенныхместах.
(Способ определения этих мест сильно различается для разных платформ иреализаций.) Двойные кавычки означают, что заголовочный файл – пользовательский, иего поиск начинается с того каталога, где находится исходный текст программы.Заголовочный файл также может содержать директивы #include. Поэтому иногдатрудно понять, какие же конкретно заголовочные файлы включены в данный исходный21С++ для начинающихтекст, и некоторые заголовочные файлы могут оказаться включенными несколько раз.Избежать этого позволяют условные директивы препроцессора.
Рассмотрим пример:#define BOOKSTORE_H/* содержимое файла bookstore.h */#ifndef BOOKSTORE_H#endifУсловная директива #ifndef проверяет, не было ли значение BOOKSTORE_H определеноранее. (BOOKSTORE_H – это константа препроцессора; такие константы принято писатьзаглавными буквами.) Препроцессор обрабатывает следующие строки вплоть додирективы #endif. В противном случае он пропускает строки от #ifndef до # endif.Директива#define BOOKSTORE_Hопределяет константу препроцессора BOOKSTORE_H. Поместив эту директивунепосредственно после директивы #ifndef, мы можем гарантировать, чтосодержательная часть заголовочного файла bookstore.h будет включена в исходныйтекст только один раз, сколько бы раз ни включался в текст сам этот файл.Другим распространенным примером применения условных директив препроцессораint main(){#ifdef DEBUGcout << "Начало выполнения main()\n";#endifstring word;vector<string> text;while ( cin >> word ){#ifdef DEBUGcout << "Прочитано слово: " << word << "\n";#endiftext.push_back(word);}// ...является включение в текст программы отладочной информации.
Например:}Если константа DEBUG не определена, результирующий текст программы будет выглядетьint main()так:{string word;22С++ для начинающихvector<string> text;while ( cin >> word ){text.push_back(word);}// ...}int main()В противном случае мы получим:{cout << "Начало выполнения main()\n";string word;vector<string> text;while ( cin >> word ){cout << "Прочитано слово: " << word << "\n";text.push_back(word);}// ...}Константа препроцессора может быть определена в командной строке при вызовекомпилятора с помощью опции -D (в различных реализациях эта опция можетназываться по-разному).
Для UNIX-систем вызов компилятора с определениемпрепроцессорной константы DEBUG выглядит следующим образом:$ CC -DDEBUG main.CЕсть константы, которые автоматически определяются компилятором. Например, мыможем узнать, компилируем ли мы С++ или С программу. Для С++ программыавтоматически определяется константа __cplusplus (два подчеркивания). Длястандартного С определяется __STDC__. Естественно, обе константы не могут быть#idfef __cplusplus// компиляция С++ программыextern "C";// extern "C" объясняется в главе 7#endifопределены одновременно. Пример:int main(int,int);Другими полезными предопределенными константами (в данном случае лучше сказатьпеременными) препроцессора являются __LINE__ и __FILE__.
Переменная __LINE__содержит номер текущей компилируемой строки, а __FILE__ – имя компилируемогофайла. Вот пример их использования:23С++ для начинающихif ( element_count == 0 )cerr << "Ошибка. Файл: " << __FILE__<< " Строка: " << __LINE__<< "element_count не может быть 0";Две константы __DATE__ и __TIME__ содержат дату и время компиляции.Стандартная библиотека С предоставляет полезный макрос assert(), который проверяетнекоторое условие и в случае, если оно не выполняется, выдает диагностическоесообщение и аварийно завершает программу. Мы будем часто пользоваться этимполезным макросом в последующих примерах программ.
Для его применения следуетвключить в программу директиву#include <assert.h>assert.h – это заголовочный файл стандартной библиотеки С. Программа на C++ можетссылаться на заголовочный файл как по его имени, принятому в C, так и по имени,принятому в C++. В стандартной библиотеке С++ этот файл носит имя cassert. Имязаголовочного файла в библиотеке С++ отличается от имени соответствующего файла дляС отсутствием расширения .h и подставленной спереди буквой c (выше ужеупоминалось, что в заголовочных файлах для C++ расширения не употребляются,поскольку они могут зависеть от реализации).Эффект от использования директивы препроцессора #include зависит от типазаголовочного файла. Инструкция#include <cassert>включает в текст программы содержимое файла cassert.
Но поскольку все имена,используемые в стандартной библиотеке С++, определены в пространстве std, имяassert() будет невидимо до тех пор, пока мы явно не сделаем его видимым с помощьюследующей using-директивы:using namespace std;Если же мы включаем в программу заголовочный файл для библиотеки С#include <assert.h>то надобность в using-директиве отпадает: имя assert() будет видно и так2.(Пространства имен используются разработчиками библиотек для предотвращениязасорения глобального пространства имен. В разделе 8.5 эта тема рассматривается болееподробно.)1.4.
Немного о комментарияхКомментарии помогают человеку читать текст программы; писать их грамотно считаетсяправилом хорошего тона. Комментарии могут характеризовать используемый алгоритм,2 Как было сказано ранее, не все компиляторы поддерживают пространства имен, поэтомуэта разница проявляется только для последних версий компиляторов.24С++ для начинающихпояснять назначение тех или иных переменных, разъяснять непонятные места. Прикомпиляции комментарии выкидываются из текста программы поэтому размерполучающегося исполняемого модуля не увеличивается.В С++ есть два типа комментариев. Один – такой же, как и в С, использующий символы/* для обозначения начала и */ для обозначения конца комментария. Между этимипарами символов может находиться любой текст, занимающий одну или несколько строк:/** Это первое знакомство с определением класса в C++.* Классы используются как в объектном, так и в* объектно-ориентированном программировании.