Оператор

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