4_lektsia_S.ppt
- Количество слайдов: 42
Перечисления (enum) • Перечислимый тип (enumerated type) служит для объявления символических имен, представляющих целочисленные константы. • Можно сказать, что это тип данных, заданных списком принадлежащих ему значений. • Назначение перечислимых типов заключается в том, чтобы повысить удобочитаемость программы.
Перечисления (enum) • Формат: enum [ имя_типа ] { список_констант }; • Имя типа задается в том случае, если в программе требуется определять переменные этого типа. • Компилятор обеспечивает, чтобы эти переменные принимали значения только из списка констант.
Перечисления (enum) • Константы должны быть целочисленными и могут инициализироваться обычным образом. • При отсутствии инициализатора первая константа обнуляется, а каждой следующей присваивается на 1 большее значение, чем предыдущей: enum Err { ERR_READ, ERR_WRITE, ERR_CONVERT}; • Константам ERR_READ, ERR_WRITE, ERR_CONVERT присваиваются значения 0, 1 и 2 соответственно.
Перечисления (enum) enum spectrum {red, green, blue, violet}; orange, yellow, Имя переменной enum spectrum color; color enum {two = 2, three, four, ten = 10, eleven, fifty = 50}; enum levels {low = 100, medium = 500, high = 2000}; enum Forms{ share, spere, cylinder}; enum {SUN, MON, TUES, FRI=5, SAT} day; day Имя переменной
Перечисления (enum) • В общем случае перечислимые константы имеют тип int. • К перечислимой переменной можно применять операции инкрементирования ++ и декрементирования – –. Например, for (color = red; ++color) { ; } color <= violet;
Перечисления (enum) #include
Перечисления (enum) switch (a. Month) { // 31 день case january: case march: case may: case july: case august: case october: case december: days = 31; break; // 30 дней case april: case june: case september: case november: days = 30; break;
Перечисления (enum) case february: days = 28; break; default: printf("nt Wrong number of the monthn"); days = 0; break; }
Перечисления (enum) if (days) printf("n The number of days of the month: %dn", days); if (a. Month == february) printf("n. . . or 29 if it is a leap yearn"); printf("nn Press any key: "); _getch(); return 0; }
Объявление нового типа данных typedef тип новое_имя [ размерность ]; Размерность может отсутствовать. Имя нового типа typedef enum {FALSE, TRUE} boolean; typedef unsigned int UINT; Имя typedef char Msg[100]; нового типа typedef struct{ Имя char fio[30]; нового типа int date, code; float salary; } Worker; Имя нового типа 10
Объявление нового типа данных Введенное таким образом имя можно использовать таким же образом, как и имена стандартных типов: //две переменных типа unsigned int UINT i, j; //массив из 10 строк по 100 символов Msg str[10]; //массив из 100 структур Worker stuff[100]; //переменная перечисляемого типа boolean flag;
Директивы препроцессора • Препроцессор (англ. preprocessor) – программа, выполняющая предварительную обработку входных данных для другой программы. • Препроцессор просматривает программу до компилятора и заменяет в ней определенные сочетания символов (символические аббревиатуры) на соответствующие директивы. • Препроцессор отыскивает и подключает к программе необходимые файлы и может изменить условия компиляции.
Директивы препроцессора • Строки, начинающиеся со знака # (перед которыми разрешены символы пустого пространства), задают препроцессору инструкции-директивы. • Каждая директива препроцессора должна занимать отдельную строку. #include
Директивы препроцессора • Имеются следующие препроцессора: директивы #define #endif #ifdef #line #elif #error #ifndef #pragma #else #if #include #undef
Директива #include • Используется для включения в исходный текст программы файлов, содержащих прототипы стандартных функций и части исходных текстов программы. • Имя исходного (подключаемого) файла должно быть заключено в двойные кавычки или угловые скобки.
Директива #include <Имя файла> – в этом случае файл ищется в каталогах среды – эта форма используется при подключении стандартных файлов Си и С++; #include ″Имя файла″ – в этом случае файл сначала ищется в текущем каталоге проекта, а потом уже в каталогах среды – такая форма используется при подключении файлов конкретного проекта.
Директива #include • Файлы, имена которых находятся в директивах #include, могут в свою очередь содержать другие директивы #include. Они называются вложенными. • Количество допустимых уровней вложенности у разных компиляторов может быть разным. • В стандарте С 89 предусмотрено, что компиляторы должны допускать не менее 8 таких уровней.
Директива #define • Используется для описания макроопределений – текстовых строк, вставляемых препроцессором вместо указанных имен (макрокоманд). Вставляемые фрагменты можно настраивать с использованием специально задаваемых параметров.
Директива #define <Идентификатор>[(<Список параметров>)] <Строка> • <Идентификатор> – имя, используемое для идентификации строки (макрокоманда); • <Список параметров> – список идентификаторов, обозначающих заменяемые элементы строки – может отсутствовать; • <Строка> – строка-макроопределение, заменяющая имя в тексте программы.
Директива #define nil 0 // определяет замену идентификатора nil нулем #define N 5 // определяет замену идентификатора N числом 5 int A[N][N]; … #define MSG ″Это строка - пример″ // определяет замену идентификатора // MSG заданной строкой
Директива #define P(X) printf(″X равен %d. n″, X) /* определяет замену идентификатора P с параметром X на строку вывода данного параметра */ P(alf) //printf(″alf равен %d. n″, alf) #define MAX(X, Y) (X>Y? X: Y) int main() { int x=5, y; y= MAX(x, 2); cout << y << endl; cout << MAX (7, x) << endl; return 0; }
Директива #define • Имена макросов обычно задаются с помощью букв верхнего регистра. • Когда в программе встречается имя макроса, используемые в его определении формальные параметры заменяются теми аргументами, которые есть в программе. • Такого рода макросы называются макросами с формальными параметрами (макроопределениями с параметрами и макросами, напоминающими функции).
Директива #define Формальные подстановки, выполняемые посредством #define, могут привести к неожиданным ошибкам, например: #define ABS(X) (X>0? X: -X) void main() { int i, j; … i= ABS(j++); // Ошибка! j++ будет выполнено дважды }
Директива #undef Используется для отмены команды #define. Формат команды: #undef <Имя> После выполнения этой команды замена идентификатора на строку прекращается. #define TABLE_SIZE 100 int table 1[TABLE_SIZE]; #undef TABLE_SIZE #define TABLE_SIZE 200 int table 2[TABLE_SIZE];
Директивы условной компиляции • Директивы условной компиляции дают возможность выборочно компилировать части исходного кода программы. • Этот процесс называется условной компиляцией. • При этом используются две конструкции.
Директивы условной компиляции #if <Константное выражение> <Операторы языка и команды препроцессора> [#else <Операторы языка и команды препроцессора>] #endif
Директивы условной компиляции #if <Константное выражение 1> <Операторы языка и команды препроцессора > #elif <Константное выражение 2> <Операторы языка и команды препроцессора> [#else <Операторы языка и команды препроцессора>] #endif
Директивы условной компиляции • Если находящееся за директивой #if константное выражение истинно, то компилируется следующие за #if операторы языка и команды препроцессора. • Константное выражение может быть задано через директиву #define. • Директива условной компиляции #else используется практически так же, как в обычном условном операторе языка С: if – else.
Директивы условной компиляции • Аналогично используются директивы #elif (else if). • Если константное выражение в директиве #elif истинно, то будет компилироваться соответствующая последовательность операторов программного кода. При этом другие выражения в директивах #elif проверяться уже не будут, в том числе директива #else.
Директивы условной компиляции • В соответствии со стандартом С 89 у директив #if и #elif может быть не менее 8 уровней вложенности. • При вложенности каждая директива #endif, #else или #elif относится к ближайшей директиве #if или #elif. • Каждая директива #if сопровождается директивой #endif.
Директивы условной компиляции #ifdef имя_макроса последовательность операторов #endif • Директива условной компиляции #ifdef означает «if defined» (если определено). • Последовательность операторов будет компилироваться, если имя макроса было определено ранее с помощью директивы #define.
Директивы условной компиляции #ifndef имя_макроса последовательность операторов #endif • Директива условной компиляции #ifndef означает «if not defined» (если не определено). • Последовательность операторов будет компилироваться, если имя макроса еще не определено директивой #define. • В директивах #ifdef и #ifndef можно использовать #else или #elif.
Директивы условной компиляции #ifdef TABLE_SIZE int table[TABLE_SIZE]; #endif #ifndef TABLE_SIZE #define TABLE_SIZE 100 #endif int table[TABLE_SIZE];
Директивы условной компиляции #if TABLE_SIZE>200 #undef TABLE_SIZE #define TABLE_SIZE 200 #elif TABLE_SIZE<50 #undef TABLE_SIZE #define TABLE_SIZE 50 #else #undef TABLE_SIZE #define TABLE_SIZE 100 #endif int table[TABLE_SIZE];
Директивы условной компиляции #if !defined TABLE_SIZE #define TABLE_SIZE 100 #elif defined ARRAY_SIZE #define TABLE_SIZE ARRAY_SIZE int table[TABLE_SIZE]; #endif
Директива #error • Заставляет компилятор прекратить компиляцию, используется в основном для отладки. Когда встречается эта директива, то выводится сообщение об ошибке. #error сообщение – об – ошибке • Заданное сообщение об ошибке в двойные кавычки не заключается. #if !define(MODEL) #error Building model not defined #endif
Директивы условной компиляции #if defined(NEARPOINTERS) space=farcoreleft(); #elif defined(FARPOINTERS) space=coreleft(); #else #error Unsupported memory model #endif
Операторы препроцессора # и ## • Операторы # и ## применяются в сочетании с директивой #define. • Оператор #, который обычно называют оператором превращения в строку (stringize), трансформирует аргумент, перед которым стоит, в строку, заключенную в кавычки. • Оператор ##, называемый оператором склеивания (pasting), или конкатенации, конкатенирует две лексемы. Операция ## должна иметь два операнда.
Операторы препроцессора # и ## #define str(x) #x cout << str(test); cout << "test"; #define glue(a, b) a ## b glue(c, out) << "test"; cout << "test";
Операторы препроцессора # и ## #define CHAR_COD(c) ""#c"" int main (void) { char ch; printf("n Введите символ: "); scanf("%c", &ch); printf("n %s "%c", его код %d", CHAR_COD(Символ), ch); printf("nn. . . Нажмите любую клавишу: "); _getch(); return 0; }
Операторы препроцессора # и ## #define TWO_LEXEME(a, b) #define CHAR_COD(c) a ## b ""#c"" int main (void) { char ch; printf("n Введите символ: "); scanf("%c", &ch); if (!(ch % 2)) printf("n %s "%c", его код %d %s", CHAR_COD(Символ), ch, TWO_LEXEME(" - четный", "!")); ", "!")
Операторы препроцессора # и ## else printf("n %s "%c", его код %d %s", CHAR_COD(Символ), ch, TWO_LEXEME(" - не “, "четный. ")); . ") printf("nn. Нажмите любую клавишу: "); _getch(); return 0; }


