Общие условия выбора системы дренажа: Система дренажа выбирается в зависимости от характера защищаемого...
История развития хранилищ для нефти: Первые склады нефти появились в XVII веке. Они представляли собой землянные ямы-амбара глубиной 4…5 м...
Топ:
Генеалогическое древо Султанов Османской империи: Османские правители, вначале, будучи еще бейлербеями Анатолии, женились на дочерях византийских императоров...
Оснащения врачебно-сестринской бригады.
Теоретическая значимость работы: Описание теоретической значимости (ценности) результатов исследования должно присутствовать во введении...
Интересное:
Уполаживание и террасирование склонов: Если глубина оврага более 5 м необходимо устройство берм. Варианты использования оврагов для градостроительных целей...
Финансовый рынок и его значение в управлении денежными потоками на современном этапе: любому предприятию для расширения производства и увеличения прибыли нужны...
Наиболее распространенные виды рака: Раковая опухоль — это самостоятельное новообразование, которое может возникнуть и от повышенного давления...
Дисциплины:
2017-09-28 | 268 |
5.00
из
|
Заказать работу |
|
|
Язык Си позволяет дать новое название уже существующим типам данных. Для этого используется ключевое слово typedef и при этом новый тип не создается.
typedef < имя ранее определенного типа >< имя нового типа1>
[,<имя нового типа2>…];
Новое имя становится синонимом имен ранее определенным.
Например:
typedef float real; Теперь вместе fboat можно использовать real.
typedef char symbol;
Часто используется для переопределения структур.
Typedef struct st
{
char name [30];
char group [4];
int god;
} STUDENT;
Теперь для определения переменной можно записать st AN;
или STUDENT AN;
Область действия зависит от расположения оператора typedef. Если определение находится внутри функции, то область действия локальна и ограничена этой функцией. Если вне, то – глобальна.
С typedef может быть объявлен любой тип, включая указатели, функции и массивы, структуры и объединения.
Пример1.
typedef char arr [40]; // FIO- массив символов
arr FIO, *adres; // adres- указатель на массив символов
Это эквивалентно char FIO[40], *adres;
Пример2.
typedef int* Pi; //объявлен новый тип Pi-указатель на целое.
typedef void (*pfn) (); //объявлен новый тип pfn-указатель на функцию, не-
возвращающую значения, с любым списком типов аргументов.
typedef void (*pfnI) (int); // объявление типа pfnI-указатель на функцию с
одним аргументом типа int, невозвращающую значения
typedef void (*pptn[10]) (); //объявление типа pptn- массив из 10 указателей на
функцию, не возвращающую значения, с любым списком аргументов.
Объявление typedef применяется
1) для создания удобных распознаваемых имен часто встречающихся;
2) для вложенных типов;
а также, чтобы сделать программы переносимыми для различных целых типов.
Файлы
Прежде чем читать информацию из файла или записывать в него, нужно его открыть. В библиотеке <stdio.h> для этого имеется специальная функция
|
FILE *fopen(char *fname, char *mode);
где *fname – имя файла, *mode – режим (табл.3).Функция возвращает указа-тель (ссылку) на файл, который должен быть предварительно описан.
Например, FILE *fu; * fu – указатель на файловый тип
Пример. Объявим указатели на переменные файлового типа
FILE *uin, *uout; // (указатели на переменные файлового типа)
uin = fopen(“name1”, “r”); // открыть файл “name1” для чтения и далее
идентифицировать как uin
uout = fopen(”name2”, “w”); // открывается для записи и связывается с
идентификатором uout.
Если производиться открытие несуществующего файла, то он создается.
Для открытия файла с именем test рекомендуется метод, который позволяет определить ошибку при открытии файла.
# include <stdio.h> // работа с файлами и константа NULL (FILEOPEN.C)
# include <stdlib.h> //для ф-ии exit()
Void main()
{
FILE *fp;
if ((fp=fopen("test","w"))==NULL)
{
puts("Не могу открыть файл\n "); // печать строки
exit(1);
}
puts("Файл открыт\n");
}
Таблица 3
Таблица режимов для открываемого файла
Режим | Действие |
“r” | Открыть для чтения |
“w” | Создать для записи |
“a” | Открыть для добавленияв существующий файл |
“rb” | Открыть двоичный файл для чтения |
“wb” | Создать двоичный файл для записи |
“ab” | Открыть двоичный файл для добавления |
“r+” | Открыть для чтения и записи |
“w+” | Создатьдля чтения и записи |
“a+” | Открыть для добавления или создать для чтения и записи |
“r+b” | Открыть двоичный файл для чтения и записи |
“w+b” | Создать двоичный файл для чтения и записи |
“a+b” | Открыть двоичный файл для добавления или создать для чтения и записи |
“rt” | Открыть текстовыйфайл для чтения |
“wt” | Создать текстовый файл для записи |
“at” | Открыть текстовый файл для добавления |
“r+t” | Открыть открыть текстовый файл для чтения и записи |
“w+t” | Создать текстовый файл для чтения и записи |
“a+t” | Открыть текстовый файл для добавления или создать для чтения и записи |
В библиотеке <stdio.h> определены также следующие функции работы с файлами (fp- указатель на файл, возвращаемый функцией):
|
fopen () - открытие файла;
int fclose(FILE *fp) - закрытие файла. Возвращает нуль, если операция выполнена успешно и иное значение в противном случае. Функция является рекомендуемой, поскольку файлы при нормальном завершении закрываются автоматически;
int puts(int ch, FILE *fp) - записать символа типа int в поток. Возвращается записанный символ, если операция была успешной. Если произошла ошибка возвращается EOF;
int gets(FILE *fp) - прочесть символ типа int из потока. Возвращает EOF, если достигнут конец файла, или произошла ошибка при чтении файла;
int feof(FILE *fp) - возвращает значение «истинно», если достигнут конец файла и нуль в противном случае;
Пример. while (!feof(fp)) {ch=getc(fp);}
Выполняется ввод символа, пока не достигнут конец файла;
int ferror(FILE *fp) - возвращает значение нуль, если обнаружена ошибка. Рекомендуется для обнаружения ошибок чтения и записи после каждой операции с файлами;
int fprintf(FILE *fp, const, char *string, …) - форматированная запись в файл. Содержит указатель на файл и управляющую строку со списком;
int fscanf(ILE *fp, const,char *string) – форматированное чтение из файла;
unsign fread(void *buf, int bytes, int c, FILE *fp) - читает блок данных из потока (буферный обмен); buf - указатель на область памяти, откуда проис-ходит обмен информации. с - количество единиц записи длиной bytes, которая будит считываться.
unsign fwrite(void *buf, int bytes, int c, FILE *fp) - пишется блок данных в поток;
int remove(char *filename) - уничтожается файл, возвращается нуль при успешной операции;
unsign rewind(FILE *fp) - устанавливается указатель на начало файла;
int fseck(FILE *fp, long numbyte, int orig) - установить указатель позиции файла в заданное место, numbyte - количество байт от точки отсчета (0,1,2), orig – макрос 0 - начало, 1- текущая позоция, 2 - конец;
void abort() - <stdlib.h> - немедленное прекращение программы без закрытия файлов и без освобождения буферов.
2.10 Операторы динамического распределения памяти в С++
В С++ введены 2 «интеллектуальных» оператора new и delete, освобождающие про-граммиста от необходимости явно использовать библиотечные функции malloс, calloс и free.
Оператор new выделяет блок памяти, необходимый для размещения переменной или массива (необходимо указывать тип и, в случае массива, размерность), и при этом можно присваивать вновь созданной переменной начальное значение.
|
New type_name [ (инициатор) ]; или New (type_name [ (инициатор) ]);
Возвращает указатель на объект а= new int[n] для неизвестного числа элементов. Оператор delete освобождает ранее выделенную память. Размер занятого блока для правильной работы delete, записывается в его начало и обычно занимает дополнительно 4 байта.
Примечание: Следует помнить, что реальный размер занятого блока не произволен, а кратен определенному числу байт (в С++3.0-16), поэтому, с точки зрения расхода памяти невыгодно резервировать много блоков под небольшие объекты.
В случае успешного выполнение new возвращает адрес начала занятого блока памяти, увеличенный на количество байт, занимаемых информацией о размере блока (т.е. возвращает адрес созданной переменной или адрес нулевого элемента созданного массива). Когда new не может выделить требуемую память, он возвращает значение (void *), в этом случае рекомендуется предусмотреть в программе реакцию. Например:
# include <stdio.h> //
# include <iostream.h> // для в\в в С++
int main()
{
int *u_i;
double *u_d;
char *string;
int str_len=80;
u_i= new int; //Зарезервировать место под переменную типа int и
//присвоить u_i ее адрес (Значение *u_i не определено)
u_d= new double(3.1415);// -"- и *u_d инициализируется знач. 3.1415
string=new char[str_len];
if (!(u_i && u_d && string))
{
cout<<"Не хватает памяти для всех динамически"
"размещаемых переменных!";
return 1;
}
string[0]='Y';
string[1]='e';
string[2]='s';
string[3]='!'; string[4]='\0';
cout<<"\n u_i="<<u_i<<" случайное значение *u_i="<<*u_i;
delete u_i; //Освободить блок памяти, на кот указывает u_i
cout<<"\n u_d="<<u_d<<" *u_d="<< *u_d;
delete u_d; //Освободить блок памяти, на кот указывает u_D
printf("\n string= %p ", string);
cout<<" string contents="<<string<<"\n";
delete string; // Можно и delete [str_len] string;
return 0; // но выдается предупр: размер массива игнорируется
}
Если указатель, на который действует оператор delete, не содержит адреса блока, зарегистрированного ранее оператором new, или же не равен NULL, то последствия будут непредсказуемыми.
Помимо проверки возвращаемого значения, в С++ для обработки ситуации нехватки памяти, программист может определить специальную функцию обработки, которая будет вызываться при неудачном выполнение оператора new и «пытаться» изыскать необходимую память, либо выдать сообщение и завершить выполнение программы библиотечной функцией exit или abort.
|
Директивы препроцессора
Условная компиляция
Можно избирательно компилировать части файла в зависимости от значения некоторого константного выражения или идентификатора.
Для этого служат директивы #if, #elif, #else, #endif.
Синтаксис условной конструкции:
#if <выражение1>
последовательность операторов //компилировать, если <выражение1> истинно.
#elif <выражение2>
операторы //компилировать, если <выражение1> ложно, а <выражение2> истинно
#elif <выражение3>
последовательность операторов // компилировать, если <выражения1 и 2>
ложны, а <выражение3> истинно
#else
операторы // компилировать, если все выражения ложны.
#endif // конец для условной компиляции if.
Правило выполнения условных директив.
1. Для каждого #if должна быть соотвествующая #endif.
2. Директивы #elif и #else являются опциональными (исключают друг друга).
3. Число директив #elif между #if и #endif не ограничено. Директива #else должна быть одна и находиться перед #endif.
4. Аналогично оператору if...else компилируется та секция, которая соответс-твует первому истинному выражению.
5. Если ни одно из выражений не истинно, то компилируется секция, следую-щая за частью #else.
6. Значение выражения должно быть целой константой; в выражении нельзя использовать операцию sizeof и преобразование типов.
Оператор defined или знак операции препроцессора
Он может применяться в директивах #if и #elif и позволяет проверить, был ли определен идентификатор или макрос.
void ShowMessage(char *msg)
{
# if defined(DOS_target)
puts(msg);
# else MessageBox(NULL,msg,''MSG'',MB_OK);
# endif
}
Если макрос DOS_target определен, то функция ShowMessage использует для вывода сообщения функцию puts, в противном случае компилируется функция MessageBox для специального вывода.
Можно применять логическую операцию! для проверки того, что иденти-фикатор не определен. Функцию void ShowMessage(DOS_target) можно перепи-сать таким образом
{ # if!defined(DOS_target)
MessageBox(NULL,msg,''MSG'',MB_OK);
# else
puts(msg);
# endif
}
Директивы #ifdef и #ifndef
Эти директивы эквивалентны соответственно #if defined и #if!defined и позволяют проверить, определен идентификатор в данный момент или нет. Однако применение оператора defined является более предпочтительным, т.к. он позволяет проверить сразу несколько макросов в сложных логических выражениях.
# ifdef DOS_target можно упростить до # if defined (DOS_target)
# ifndef NDEBUG &&!defined(NDEBUG)
puts(msg); puts(msg);
# endif # endif
# endif
Данные директивы требуют наличия соответствующей директивы #endif, между ними может (но не обязательно) размещаться директива #else или #elif.
Директива #error
Позволяет выдавать во время компиляции сообщение об ошибке.
|
Ее структура: #error <сообщение об ошибке>
Сообщение может включать в себя идентификаторы макросов, которые будут расширены препроцессором. Она применяется, обычно, когда не был определен необходимый идентификатор.
Директива #line
Позволяет изменить внутренний счетчик строк компилятора и имеет
Структуру: #line номер строки["имя файла"]
Номер строки должен быть целой константой. В строке может присутство-вать опциональное имя файла. Эта директива изменяет предопределенный макрос _ _LINE_ _. Если присутствует имя файла, то меняется макрос
_ _FILE_ _. Директива используется, чтобы в процессе трансляции заменить наименование текущего файла исходного текста программы и (или) номер строки этого текста.
Предопределенные макросы
Компилятор автоматически определяет некоторые макросы ANSI.(ANSI – официальное название стандарта языка Си, препроцессора и библиотеки поддержки выполнения программы, принятое Американским Национальным институтом Стандартов)
__DATE__ - строка, представляющая дату, когда данный файл обрабатывался препроцессором (форма даты mm dd yyyy).
__FILE__- строка, представляющая имя текущего файла в двойных кавычках.
__LINE__- целое, представляющее текущий номер строки.
__STDC__- значение является константой, равной 1, если установлено со-ответствие со стандартом ANSI, в противном случае макрос не определен.
__TIME__- строка, представляющая время в форме hh:mm:ss, когда данный файл обрабатывался препроцессором.
Директива #pragma
Позволяет управлять специфическими возможностями компилятора.
Ее синтаксис : #pragma <директива>
Если реализация системы программирования, обнаружив pragma, ее не узнает, то система ее игнорирует. (Стандартных прагм не существует.)
Директивы #pragma, поддерживаемые компилятором C++:
аrgsusd - подавляет предупреждающее сообщение о том, что параметр xхх не ис- пользован для функции, следующей за директивой;
exit - позволяет указать функцию, которая должна быть вызвана перед завер-шением программы;
еxtref - заставляет компилятор включить ссылку на неиспользованную внеш-нюю переменную или функцию;
hdrfile специфицирует имя заранее откомпилированного файла-заголовка;
hdrignore - т.к. макросы и типы, определяемые в заголовочном файле, могут изменяться, когда определяется другой макрос, компилятор не использует информацию из перекомпилированного заголовка, если встречает директиву условной компиляции. Данная директива указывает, что заголовок должен использоваться, если встречается в директиве условной компиляции;
hdrstop - предписывает компилятору не включать дальнейшую информацию, перекомпилированную в заголовочный файл;
inline - указывает, что компиляция текущего модуля должна производиться через ассемблер;
intrinsic - эта директива может быть использована, чтобы разрешить или запре-тить генерацию inline-кода для встроенной функции; (встроенная функция - это библиотечная процедура, для которой компилятор генерирует inline-код вместо вызова библиотеки);
obsolete - приводит к тому, что компилятор генерирует сообщение-предупреж-дение о том, что имя файла является устаревшей функцией. Ее можно исполь-зовать, чтобы сообщить другим программистам, что улучен код и предусмотрена для данной задачи новая функция;
option – позволяет включить в код опции командной строки компилятора;
startup – является дополнительной к #pragma exit, позволяет указать функцию, которая должна выполняться до функции main;
warn – позволяет выборочно разрешать или подавлять предупреждающее сообще-ние. Если предупреждению предшествует знак «+», то выдача сообщения разре- шается, если знак «-», то запрещается.
Некоторые компиляторы, в частности ANSI, узнают директиву pragma, которая указывает на то, как плотно упакованы смежные члены в структуру, например: #pragma pack (n), где n может быть 1,2 или 4, указывая, что имеет место выравнивание на границу байта, слова или двойного слова.
В языке С/С++ имеются также директивы подключения библиотек # include и макроподстановок #define [7, 8].
|
|
Механическое удерживание земляных масс: Механическое удерживание земляных масс на склоне обеспечивают контрфорсными сооружениями различных конструкций...
Двойное оплодотворение у цветковых растений: Оплодотворение - это процесс слияния мужской и женской половых клеток с образованием зиготы...
Состав сооружений: решетки и песколовки: Решетки – это первое устройство в схеме очистных сооружений. Они представляют...
Эмиссия газов от очистных сооружений канализации: В последние годы внимание мирового сообщества сосредоточено на экологических проблемах...
© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!