Чтение онлайн

ЖАНРЫ

Программирование. Принципы и практика использования C++ Исправленное издание
Шрифт:

Проблема с функцией

scanf
означает, что часто благоразумно и легче использовать функцию
getchar
. Типичный ввод символов с помощью функции
getchar
выглядит следующим образом:

while((x=getchar)!=EOF) {

/* ... */

}

Макрос

EOF
, описанный в библиотеке
stdio
, означает “конец файла”; см. также раздел 27.4.

Альтернативы функций

scanf("%s")
и
gets
в стандартной библиотеке языка C++ от этих проблем
не страдают.

string s;

cin >> s; // считываем слово

getline(cin,s); // считываем строку

27.6.3. Файлы

В языке C (и C++) файлы можно открыть с помощью функции

fopen
, а закрыть — с помощью функции
fclose
. Эти функции, вместе с представлением дескриптора файлов
FILE
и макросом
EOF
(конец файла), описаны в заголовочном файле
<stdio.h>
.

FILE *fopen(const char* filename, const char* mode);

int fclose(FILE *stream);

По существу, мы используем файлы примерно так:

void f(const char* fn, const char* fn2)

{

FILE* fi = fopen(fn, "r"); /* открываем файл fn для чтения */

FILE* fo = fopen(fn2, "w"); /* открываем файл fn для записи */

if (fi == 0) error("невозможно открыть файл для ввода");

if (fo == 0) error("невозможно открыть файл для вывода");

/* чтение из файла с помощью функций ввода из библиотеки stdio,

например, getc */

/* запись в файл с помощью функций вывода из библиотеки stdio,

например, fprintf */

fclose(fo);

fclose(fi);

}

Учтите: в языке С нет исключений, потому вы не можете узнать, что при обнаружении ошибок файлы были закрыты.

27.7. Константы и макросы

В языке С константы не являются статическими.

const int max = 30;

const int x; /* неинициализированная константа: OK в C

(ошибка в C++) */

void f(int v)

{

int a1[max]; /* ошибка: граница массива не является константой

(OK в языке C++) */

/* (слово max не допускается в константном

выражении!) */

int a2[x]; /* ошибка: граница массива не является константой */

switch (v) {

case 1:

/* ... */

break;

case max: /* ошибка: метка раздела case не является

константой
(OK в языке C++) */

/* ... */

break;

}

}

По техническим причинам в языке С (но не в языке C++)

неявно допускается, чтобы константы появлялись из других модулей компиляции.

/* файл x.c: */

const int x; /* инициализирована в другом месте */

/* файл xx.c: */

const int x = 7; /* настоящее определение */

В языке С++ в разных файлах могут существовать два разных объекта с одним и тем же именем

x
. Вместо использования ключевого слова
const
для представления символьных констант программисты на языке С обычно используют макросы. Рассмотрим пример.

#define MAX 30

void f(int v)

{

int a1[MAX]; /* OK */

switch (v) {

case 1:

/* ... */

break;

case MAX: /* OK */

/* ... */

break;

}

}

Имя макроса
MAX
заменяется символами
30
, представляющими собой значение этого макроса; иначе говоря, количество элементов массива
a1
равно
30
, а меткой второго раздела case является число
30
. По общепринятому соглашению имя макроса
MAX
состоит только из прописных букв. Это позволяет минимизировать ошибки, вызываемые макросами.

27.8. Макросы

Берегитесь макросов: в языке С нет по-настоящему эффективных способов избежать макросов, но их использование имеет серьезные побочные эффекты, поскольку они не подчиняются обычным правилам разрешения области видимости и типов, принятым в языках С и С++. Макросы — это вид текстуальной подстановки. См. также раздел А.17.2.

Как защититься от потенциальных проблем, связанных с макросами, не отказываясь от них навсегда (и не прибегая к альтернативам, предусмотренным в языке С++?

• Присваивайте всем макросам имена, состоящие только из прописных букв:

ALL_CAPS
.

• Не присваивайте имена, состоящие только из прописных букв, объектам, которые не являются макросами.

• Никогда не давайте макросам короткие или “изящные” имена, такие как

max
или
min
.

• Надейтесь, что остальные программисты следуют этим простым и общеизвестным правилам.

В основном макросы применяются в следующих случаях:

• определение “констант”;

• определение конструкций, напоминающих функции;

• улучшение синтаксиса;

• управление условной компиляцией.

Кроме того, существует большое количество менее известных ситуаций, в которых могут использоваться макросы.

Мы считаем, что макросы используются слишком часто, но в программах на языке С у них нет разумных и полноценных альтернатив. Их даже трудно избежать в программах на языке С++ (особенно, если вам необходимо написать программу, которая должна подходить для очень старых компиляторов или выполняться на платформах с необычными ограничениями).

Поделиться с друзьями: