Оператор
printf(FNT, X); превращается в printf(“x равен %d\n”,x);
Рассмотрим пример директивы # define с аргументами. Работать с такими директивами нужно внимательно, в противном случае можно получить неожиданные результаты.
Покажем это на примере:
Пример 2.
#include<stdio. h>
#define SQUARE(X) X*X
#define PR(X) printf(“X равен %d\n”,X)
main( )
{ int x=4;
int z;
z = SQUARE(x);
PR(z);
PR(SQUARE(z));
PR(SQUARE(x+2));
pr(100/SQUARE(2));
}
Всюду, где в программе SQUARE(x) оно заменяется на x*x.
Результат работы программы:
z равно 16
Z равно 4
SQUARE (x+2) равно 14
100/SQUARE (2) равно 100
Первые две строки предсказуемы. Заметим, что даже внутри кавычек в определении PR переменная замещается соответствующим аргументом.
Строка
PR(SQUARE (x));
замещается на следующую
printf(“SQUARE(x) равно %d\n”,SQUARE (x));
после первого этапа макрорасширения. Второе SQUARE (х) превращается в Х*Х, а первое остаётся без изменении, потому что теперь находится внутри кавычек в операторе программы и защищено от дальнейшего расширения. Окончательно строка программы содержит printf(“SQUARE (x) равно %d\n”,X*X); и выводит на экран.
SQUARE (х) равно 16
Теперь мы добрались до несколько специфических результатов.
Вспомним, что Х имеет значение 4. Это позволяет предположить, что SQUARE (Х+2) будет равно 6*6 или 36. Но напечатанный результат говорит, что получается 14. Причина этого несоответствия состоит в том, что препроцессор не делает вычислении, он только замещает сторону, таким образом, везде вместо Х будет подставлено Х+2. Значит Х*Х ставится Х+2*Х+2. Если Х равен 4, то 4+2*4+2=14
Если всё-таки требуется, чтобы SQUARE (х+2) было равно 36, то необходимо записать так:
# define SQUARE(X) (X)*(X)
Тогда SQUARE (Х+2) становится (Х+2)*(Х+2), и мы получим желаемый результат.
Рассмотрим следующий результат. Выражение 100/SQUARE (Х) превращается в 100/2*2, т. е. равно 100.
Эту путаницу можно исправить, определив SQUARE (Х) следующим образом
# define SQUARE (X) (X)*(X)
это даёт 100/(2*2)
Чтобы выполнить два последующих примера, нам необходимо определение
# define SQUARE (Х) (Х)*(Х)
Пример 3. В приведённой программе открывающая и закрывающая фигурные скобки заменены словами begin и end. Определены также другие названия для функции ввода-вывода. В результате получилось что-то среднее между программой на Паскале и СИ. Таким образом, пользователь, работающий с другим языком может строить привычные для себя конструкции.
#include <stdio. h>
#define write(valw) printf(“%d”,valw) /*выполняется замена строки write(valw) на строку printf(“%d”,valw)*/
#define read(valr) scanf (“%d”,$valr) /* выполняется замена строки read(valr) на строку scanf(“%d”,&valr)*/
#define begin { /* выполняется замена слова begin на скобку {*/
#define end } /* выполняется замена слова end на скобку }*/
main( )
{begin
int i;
read (i); /*вводится с клавиатуры значение переменной i */
write (i); /*выводится на экран значение i */
end
}
Директива #undef отменяет самое последнее определение поименованного макроопределения. Она имеет следующий вид :
#undef идентификатор
где идентификатор – идентификатор, раннее определённый в директиве #define. Например:
#undef ESCAPE
после выполнения этой процедуры идентификатор ESCAPE становится неопределённым.
1.1.2. Директивы #if, #ifdef, #ifndef, #else, #endif.
Директивы. рассматриваемые в этом разделе позволяют выполнить условную компиляцию. Условная компиляция - это выборная компиляция только тех частей программы, которые удовлетворяют некоторым условиям. Одна из целей условной компиляции - сделать программу более мобильной. Изменяя несколько ключевых определений в начале файла, вы можете устанавливать различные значения и включать различные файлы для разных систем; таким образом, ненужный код не хранится в памяти во время выполнения. Решение о включении той или иной части программы применяется на этапе компиляции, а не во время выполнения.
Директива #if похожа на обычный оператор if:
#if константное выражение.
Она проверяет, будет ли отличаться от нуля выражение, составленное и константное. Выражение истинно, если оно не равно нулю. Например:
#if sys==”IBM”
#include “ibm. h”
#endif
Как видно из примера, оно заканчивается директивой #endif.
Директива
#ifdef идентификатор
Устанавливает, определён ли в данный момент идентификатор, т. е. входил ли он в команду вида #define.
Директива
#ifndef идентификатор
проверяет, не определен ли в данный момент указанный идентификатор.
Например:
#ifndef SIZE
#define SIZE 128
#endif
В результате переменная SIZE получает значение 128, если ранее она не была определена программистом. За любой из перечисленных выше директив может следовать произвольное количество строк.
Указанные директивы могут быть применены вместе с инструкцией #else. Назначение этой инструкции такое же, как и в условном операторе. Рассмотрим пример.
#ifdef MAVIS
#include “horse. h”
#define STABLE 5
#else
#include “cow. h”
#define STABLE 15
#endif
Директива #ifdef сообщает, что если идентификатор MAVIS определен препроцессором, то выполняются все последующие директивы вплоть до #else. В противном случае будут выполнены директивы, стоящие после #else до директивы #endif.
2. Задание
Взять задание из лабораторной работы №4. Написать программу, используя операторы Паскаля. Применив директивы препроцессора языка С++, обеспечит замену операторов Паскаля на операторы языка С++; выполнить программу.
3. Литература
Язык C++: Учебное пособие. - М.: Финансы и статистика,1995, - 560 с. зык программирования С++. - М.: Радио и связь, 1991. - 352 стр. Практический курс Turbo C++. Основы объектно - ориентированного программирования. - М.: Свет, 1993. - 236 с. Программирование на языке C++. Практический подход. - М.: Компьютер, 1993. - 160 с. зык турбо Cu. - М.: Мир, 1991. - 384 с. , Приглашение к Cu. - Мн.: Высш. Шк., 1990,- 224 с. , Программирование на языке Cu. - Мн.: Высш. Шк., 1991. - 156 с.
Лабораторная работа №8
“Работа с файлами в языке программирования С++”
Цель работы: научиться работать с файлами прямого и последовательного доступов. Ознакомиться с функциями, позволяющими создать, дополнить и прочитать файл, а также с функциями, обеспечивающими запись информации в файл и считывающими информацию из файла.
1. Теоретические сведения
1.1. Файлы последовательного доступа
При последовательном доступе обмен информации производится через специальный буфер, резервируемый системой ввода-вывода. Компиляция языка С++ рассматривает ввод-вывод как поток файлов, которые поступают последовательно, байт за байтом. Каждый поток связывается с файлом на магнитном диске или с файлом, который поставлен в соответствии физическому устройству, например клавиатуре. Связь потока с файлом устанавливается при его открытии. Открытие файла осуществляется функцией fopen. Данная функция возвращает указатель на файл. Указатель на файл необходимо объявлять, например:
FILE * lst;
Здесь FILE-имя типа, описанное в стандартном определении stdio. h;
lst ‑ указатель на файл (логическое имя).
Обращение к функции fopen в программе производится так:
lst = fopen (физическое имя файла, вид использования файла);
Физическое имя файла может, например, быть “prn”‑ для устройства печати;
“b:zni. f”-для файла zni. f на дискете b:
Вид исполнения.
Если файл открывается для записи или дополнения, но ещё не существует, то он создаётся. Открытие существующего файла для записи приводит к уничтожению его старого содержимого. Попытка прочитать несуществующий файл-это ошибка (fopen выдаёт указатель со значением NULL).
Для работы с файлами используются библиотечные функции fprintf, fscanf, fgets, fputs. Их применение рассмотрим ниже на примерах. После окончания работы с файлом он должен быть закрыт. Это делается с помощью библиотечной функции fclose, например:
fclose (lst)
lst ‑ указатель на файл;
Рассмотрим организацию ввода информации на печатающее устройство:
/*Работа с файлами (вывод на печатающее устройство )*/
#include<stdio. h>
main ( )
{
int i = 150;
FILE *lst;
/*lst-указатель на файл ( объект типа FILE)*/
lst= fopen (“prn”,”w”);
lst получает адрес открытого файла с именем prn, предназначенного для записи в него информации (символ w);
prn ‑ стандартное имя устройства печати, информация из файла с адресом lst будет выводится на печатающее устройство.
fprintf(lst,”\n число i = %d\n”,i) ;
первый параметр функции fprintf ‑ это указатель на соответствующий файл; на печать будет выведена строка: число i = 150.
fclose (lst);
функция fclose закрывает файл с указателем lst теперь ссылку lst можно использовать для другого файла.
Функция fprintf подобна функции printf и отличается от неё тем, что в качестве первого параметра использует указатель на соответствующий файл.
Следующая программа показывает организацию вывода информации на дискету:
/* Работа с файлами (запись информации в файл на дискету)*/
#include < stdio. h >
main ( )
{
int i = 150
FILE *rsd;
rsd = fopen(“B:ZNI. F”,”r ”);
/*второй параметр функции fopen-теперь “r ”,говорящий о чтении информации*/
fscanf(rsd,”%d”,&i);
/*из файла ZNI. F(дискета В:) будет прочитано значение i*/
printf(“число i=%d(начальное значение i)\n”,i);
while (fscanf(rsd,”%d”,&i)!=EOF)
printf(“число i = %d\n, i”);
/*последовательный вывод целых чисел из файла; вывод прекращается, когда будет достигнут конец файла(ЕОF)*/
fclose(rsd);
}
Первая функция fscanf обеспечивает чтение из файла B:ZNI. F значение целого числа i. Затем полученное значение выводится функцией printf на экран дисплея. Последующий фрагмент программы (начиная с оператора while) позволяет вывести другие целые числа из этого файла, если их там не более одного. После того как чисел в файле не остаётся, функция fscanf выдаёт особое значение EOF-признак конца файла. Его можно использовать для прекращения чтения информации.
|
Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |


