Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Tekhnologia_programmirovania.pdf
Скачиваний:
182
Добавлен:
08.04.2015
Размер:
1.76 Mб
Скачать

227

Глава 16. Программы из нескольких файлов

Исходная программа на C++ может располагаться в одном файле, но это становится неудобными или даже невозможным для больших программ. В этом случае текст программ размещается в нескольких файлах. Это удобно, так как небольшой код можно легко понять и отладить. Кроме того, работу можно распределить между несколькими программистами.

Средством работы с программами, состоящими из нескольких файлов, являются проекты, объединяющие файлы, из которых состоит программа. В проект могут входить cpp-файлы с исходным кодом, obj- файлы, с откомпилированным кодом. Заголовочные h-файлы в проект не включаются, так как они вставляются в состав других файлов директивой препроцессора #include.

При создании проекта необходимо обеспечить, чтобы функция или переменная, определенная в одном файле, была видима в другом. Это достигается с помощью объявлений переменных или функций перед их использованием. Переменные, определенные во внешнем файле, становятся видимыми в другом файле после их объявления с ключевым словом extern. При объявлении функций слово extern можно не использовать.

16.1. Работа с проектами

Проекты в Turbo C++

В среде TC новый проект создается командой меню Project, Open Project…, при этом появляется диалог Open Project File, рис.71. В поле Open Project File следует ввести имя создаваемого проекта, расширение

PRJ к имени файла проекта будет добавлено автоматически при сохранении проекта. После нажатия кнопки OK откроется вначале

пустое окно проекта, рис.72. Окно проекта можно закрыть, но сам проект при этом закрыт не будет. Проект закрывается командой Project,

Close project. Окно проекта выводится на экран командой Window, Project.

Когда активно окно, проекта клавишей Ins можно добавить в проект файл, клавишей Delete удалить файл из проекта. Те же действия можно выполнить соответствующими командами меню Project. Порядок

228 16

включения файлов в проект произволен. На рис.73 показано, что в проект SumNumb.PRJ включены два объектных файла ATOF.OBJ и GETLINE.OBJ, а также файл с исходным кодом SUMNUMB.CPP. Если в окне проекта выбрать файл и нажать Enter, данный файл будет открыт в

окне редактирования.

Рис.74. Открытие и создание проекта

Для открытия существующего проекта выполняется та же команда Project, Open, и выбирается имя проекта из списка Files, рис.75.

Рис.76. Окно проекта

Для создания из проекта рабочей программы нужно выполнить одну из команд меню Compile:

Make или клавиша F9 – выполняется перекомпиляция измененных

файлов и производится сборка программы;

Link – производится сборка программы без перекомпиляции

исходных файлов;

Build all – перекомпилируются все файлы, входящие в проект.

Рабочая программа будет иметь имя, совпадающее с именем проекта и расширение .exe.

Программы из нескольких файлов 229

Проекты в C++Builder

Как уже говорилось, в C++Bulder проект создается для каждого приложения. Для управления составом проекта используются команды меню Project:

Add to Project… – добавление в проект нового файла; Remove from Project… – удаление из проекта файла.

16.2. Область действия имен

Имена имеют переменные, функции, структуры, перечисления, классы, элементы классов и структур. Когда программы становятся большими, возрастает вероятность конфликта между именами.

Зоной видимости глобальной переменной является файл. К такой переменной можно обратиться в любом месте программы от точки объявления до конца файла.

Зоной видимости локальной переменной является часть блока, в котором она определена от точки объявления до конца блока.

Локальная переменная может перекрывать глобальную переменной с тем же именем. Пример такого перекрытия демонстрируется в приводимой ниже программе.

Программа 50. Глобальные и локальные имена

В программе использовано одно и то же имя i для двух переменных: глобальной и локальной.

// Файл Glob_Loc.cpp

 

 

#include <iostream.h>

 

 

int i = 5;

 

// Глобальная переменная

int main()

 

 

{

 

 

cout << "i = " << i << endl;

// Печать глобальной переменной

int i = 1;

// Локальная переменная закрывает глобальную

cout << "i = " << i << endl;

// Печать локальной переменной

cout << "::i = " << ::i << endl;

// Печать глобальной переменной

cin.get();

 

 

return 0;

 

 

}

 

 

Программа выводит:

i = 5 i = 1 ::i = 5

230 16

Для доступа к глобальной переменной, которая не видима из-за того, что перекрыта локальной переменной с таким же именем, можно использовать оператор разрешения зоны видимости (::). Таким образом, ::i – это имя переменной из внешнего блока.

Водной зоне видимости нельзя объявлять переменные с одинаковыми именами.

Единицей компиляции в языке C++ является файл. Файл может содержать различные объявления и определения, в том числе объявления и определения переменных и функций. В одном файле можно поместить определения нескольких функций. Запрещено помещать части одной функции в различных файлах.

ВC++ запрещено определять функции внутри других функций, поэтому имя функции всегда глобально и может быть доступно в любой другой функции при соответствующем объявлении.

Областью действия имени является часть программы, в которой это имя можно использовать. Для автоматических переменных, описанных в начале функции, областью действия является эта функция. То же относится к параметрам функций, которые фактически являются локальными переменными. Имена функций и глобальных переменных видны от точки определения до конца файла без дополнительного объявления. При соответствующем объявлении функции и глобальные переменные могут быть видны в любом файле программы. Зону действия имен можно ограничить одним файлом, объявив имена

статическими.

Статические имена

Рассмотрим схематический пример программы из двух файлов.

// Файл File_1.cpp

 

int N;

// Определение внешней переменной

void f1()

// Определение функции f1

{

 

N = 1;

// Использование внешней переменной

}

 

// Файл File_2.cpp

 

void f1();

// Объявление (прототип) функции f1

extern int N;

// Объявление внешней переменной

int f2()

// Определение функции f2

{

 

f1();

// Обращение к функции f1

int k = N;

// Использование внешней переменной, k = 1

return k;

 

}

 

Программы из нескольких файлов 231

Объявление функции f1 в файле File_2.cpp делает ее известной компилятору, который может сгенерировать ее правильный вызов. Объявление внешней переменной N позволяет использовать ее в любом месте файла File_2.cpp после точки объявления. Если в проект включены оба файла, редактор связей найдет код f1, включит его в рабочую программу и сделает ссылку на него из f2. Аналогично, редактору связей будет известен адрес N, по которому к ней можно обращаться. Недостаток данной программы состоит в том, что не так-то просто понять, почему значением k будет 1. При попытке определить еще одну внешнюю переменную с именем N в файле File_2.cpp возникает ошибка на этапе редактирования связей.

Можно ограничить зону действия имен, сделав их статическими, для чего объявления нужно начинать словом static. Проиллюстрируем это примером.

// Файл File_1.cpp

 

static int N;

// Определение внешней переменной

static void f1()

// Определение функции f1

{

 

N = 1;

// Использование внешней переменной

}

 

// Файл File_2.cpp

 

void f1();

// Объявление (прототип) функции f1

extern int N;

// Объявление внешней переменной

int f2()

// Определение функции f2

{

 

f1();

// Обращение к функции f1

int k = N;

// Использование внешней переменной, k = 1

return k;

 

}

 

При компиляции файла File_2.cpp ошибок не будет, так как есть все необходимые объявления, но на этапе компоновки возникнут ошибки, так как компоновщик не найдет f1 и N, из-за ограниченности их зоны действия файлом File_1.cpp. Компоновщик выдаст сообщение об ошибке вида: Linker error…

Программа 51. Сумматор чисел

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

Строки символов можно вводить стандартным образом с помощью cin >>, разделяя вводимые числа пробелами, но в данной программе

232 16

будем читать с клавиатуры строки символов, а затем преобразовывать строки в числа.

Для чтения строк напишем функцию int readline(),

которая читает не более MAXLINE символов в массив line, извлекает из входного потока символ новой строки \n, но не помещает его в формируемую строку, и возвращает длину прочитанной строки. Массив line и предельный размер строки MAXLINE зададим как внешние переменные. Функцию readline разместим в файле Readline.cpp.

Для преобразования строк в числа с плавающей точкой напишем функцию strtof и поместим ее в отдельном файле StrTof.cpp.

Главную функцию main, которая будет вводить и суммировать числа, поместим в файле SumNumb.cpp.

Функция strtof преобразует строку цифр, в которой может быть знак и десятичная точка, отделяющая целую часть от дробной, в число двойной точности. Сначала устанавливается знак числа, затем вычисляется целая часть val. Если присутствует десятичная точка, продолжается вычисление val как целого и параллельно накапливается степень 10, на которую надо поделить val, чтобы сформировать правильное значение.

//Файл Strtof.cpp #include <ctype.h>

//strtof: преобразование строки s в double double strtof(char s[])

{

double val, pow10;

 

int i, sign;

 

for(i = 0; isspace(s[i]); i++)

// Пропуск начальных пробелов

;

 

sign = (s[i] == '-') ? -1: 1;

// Получение знака

if('+' == s[i] || '-' == s[i])

// Если есть знак,

i++;

// переходим к следующему символу

for(val = 0.0; isdigit(s[i]); i++)

// Получаем целую часть

val = val * 10 + s[i] - '0';

 

if('.' == s[i])

// Если есть десятичная точка

i++;

// Переход к дробной части

for(pow10 = 1.0; isdigit(s[i]); i++){// Получение дробной части

val = val * 10 + s[i] - '0';

 

pow10*=10.0;

// Степень 10

}

 

return sign * val / pow10;

 

}

Программы из нескольких файлов 233

Для проверки того, что символ является пробельным, применяется функция isspace, а для проверки того, что символ есть цифра – isdigit.

//Файл ReadLine.cpp #include <iostream.h>

//Объявление внешних переменных extern int MAXLINE;

extern char line[];

/* readline: читает не более MAXLINE символов в массив line, возвращает длину строки */

int readline()

{

int c, i;

for(i = 0; i < MAXLINE - 1 && (c = cin.get()) != EOF && c != '\n'; ++i)

line[i] = c;

 

line[i] = '\0';

 

return i;

// Возвращаем длину строки

}

Для чтения отдельных символов в readline применена библиотечная функция int cin.get().

В функции main читаются строки, пока не встретится строка нулевой длины (пустая), строки преобразуются в числа, которые добавляются к сумме. Очередное значение суммы выводится.

// Файл SumNumb.cpp #include <iostream.h> #include <conio.h>

int readline(); // Прототип функции чтения строки

double strtof(char[]);// Прототип функции преобразования строки в число

// Сумматор вводимых чисел int main()

{

 

double sum = 0.0;

// Сумма

extern char line[];

// Объявление массива line

while(readline() > 0)

// Пока есть строки, преобразуем

cout << (sum+=strtof(line)) << endl;// их в числа и суммируем

getch();

 

return 0;

 

}

 

// Определение внешних переменных

int MAXLINE = 100;

 

char line[100];

// Массив под строку