|
Программирование >> Структурное программирование
18.5. Замечания по компиляции программ, состоящих из нескольких исходных файлов Как ранее уже говорилось в этой книге, можно создавать программы, которые состоят из нескольких исходных файлов (см. главу 6, К.пассы и абстрагирование данных ). При создании таких программ имеются некоторые ограничения. Например, описание функции должно полностью содержаться в одном файле, оно не может распространяться на два или большее чиспо (Ъай.лов. Типичная ошибка программирования 18.1 Размещение многоточия в середине списка параметров функции. Многоточие может располагаться только в конце списка параметров. 18.4. Использование аргументов командной строки Во многих операционных системах, в частности, в DOS и UNIX, имеется возможность передачи аргументов в функцию main из командной строки, если в список параметров main включить параметры int argc и char *argv[]. Параметр argc получает значение, равное количеству аргументов командной строки. Параметр argv - это массив строк, в который помещаются значения аргументов командной строки. Обычно аргументы командной строки используются для задания опций выполнения программы и передачи программе имен файлов. В программе на рис. 18.3 выполняется посимвольное копирование одного файла в другой. Исполняемый файл этой программы называется сору. Командная строка при вызове программы сору в системе UNIX выглядит следующим образом $ сору input output Эта командная строка вызывает копирование файла input в файл output. Если при выполнении программы значение параметра argc не будет равно 3 (лексема сору учитывается как один из параметров), то программа выдает сообщение об ошибке и завершает свою работу. В противном случае, массив argv будет содержать строки сору , input и output . Второй и третий аргументы командной строки используются программой в качестве имен файлов. Файлы открываются при создании объекта inFile класса ifstream и объекта outFile класса ofstream. Если оба файла открыты успешно, символы считываются из файла input функцией-элементом get и записываются в файл output функцией-элементом put до достижения конца файла input. После этого программа завершается. Результирующий файл будет точной копией файла input. Нужно отметить, что не все операционные системы поддерживают параметры командной строки так же просто, как UNIX и DOS. ОС Macintosh и VMS, например, требуют специальных установок для обработки аргументов командной строки. Обращайтесь к руководствам по вашей операционной системе за информацией относительно обработки аргументов командной строки. Использование аргументов командной строки iinclude <iostream.h> iinclude <fstream.h> main(int argc, char *argv[]) { if (argc != 3) cout << Применяйте формат: copy входной файл выходной файл << endl; else ( ifstream inFile(argv[1], ios::in); if (!inFile) cout << argv [1] << нельзя открыть << endl; ofstream outFile(argv[2], ios::out); if (loutFile) cout argv[2] нельзя открыть endl; while ( !inFile.eof() ) outFile.put( (char) inFile.get() ); return 0; Рис. 18.3. Использование аргументов командной строки В главе 3 мы ввели понятия класса памяти и области действия. Мы узнали, что переменные, объявленные вне определения какой-нибудь функций, имеют по умолчанию класс памяти static и называются глобальными переменными. Глобальная переменная доступна для любой функции, определенной в том же самом файле после того, как эта переменная была объявлена. Глобальные переменные также доступны для функций из других файлов; однако, в этом случае глобальные переменные должны быть объявлены в каждом файле, в котором они используются. Например, если мы определяем глобальную целочисленную переменную flag в одном файле и ссылаемся на нее в другом файле, второй файл должен содержать объявление extern int flag; записанное ранее, чем переменная flag будет использована в этом файле. В приведенном объявлении, спецификатор класса памяти extern указывает компилятору, что переменная flag либо будет определена позже в том же самом файле, либо ее определение находится в другом файле. Компилятор потом сообщит компоновщику, что в файле имеется неразрешенная ссылка на переменную flag (компилятор не знает, где определена переменная flag, и перекладывает эту задачу на редактор связей). Если компоновщик не сможет найти определения для flag, он выдаст сообщение об ошибке редактирования связей и не создаст исполняемого файла. Если соответствующее определение глобальной переменной будет найдено, то компоновщик разрешит ссылки на нее, указав ее местонахождение. Совет по повышению эффективности 18.1 Глобальные переменные улучшают показатели производительности программы, потому что к ним можно обращаться непосредственно из любой функции. При этом исключаются затраты на передачу данных в функцию. Замечание по технике программирования 18.1 Если эффективность прикладной программы не является критическим параметром, то следует избегать употребления глобальных переменных, потому что они нарушают принцип минимума привилегий и затрудняют поддержку программ. Так же, как спецификатор extern используется для объявления глобальных переменных в других файлах программ, прототипы функций могут быть использованы для расширения области действия функции за пределы файла, в котором она определена. При этом не требуется использовать спецификатор extern в прототипе функции. В каждый файл, в котором вызывается функция из другого файла, нужно включить прототип этой функции и откомпилировать эти файлы (см. раздел 17.2). Прототипы функций указывают компилятору, что эти функции либо будут определены позже в этом же файле, либо их определения находятся в другом файле. В этом случае компилятор не пытается разрешать ссылки па такую функцию, эту задачу он оставляет редактору связей. Если компоновш;ик не сможет найти определение соответ-ствуюш;ей функции, он выдаст сообш;ение об ошибке. В качестве примера использования прототипов функции для расширения области действия функции, рассмотрим любую программу, содержаш;ую директиву препроцессора #include <string.h>. Эта директива включает в файл прототипы функций типа stremp и strcat. Все функции в файле могут использовать функции stremp и strcat для выполнения своих задач. Функции stremp и strcat определены где-то в другом месте и нам не нужно знать, где они определены; мы просто можем использовать их в наших программах. Редактор связей разрешит ссылки на эти функции автоматически. Благодаря этому механизму мы можем использовать функции из стандартной библиотеки. Замечание по технике программирования 18.2 Программы, соаоящие из нескольких исходных файлов, облегчают процесс повторного использования программных кодов и свидетельавуют о хорошей технике программирования. Некоторые функции могут понадобиться в других приложениях. Такие функции следует помещать в отдельные исходные файлы, каждому из которых должен соответствовать заголовочный файлы, содержащий прототипы функций. Тогда разработчики других приложений могут использовать эти функции, включая соответствующий заголовочный файл, компилируя и компонуя свое приложение с соответствующим исходным файлом. Замечание по мобильности 18.1 Некоторые системы не поддерживают имена глобальных переменных и функций длиной более шести символов. Этот факт следует учитывать при написании программ, которые будут переноситься на другие платформы. Суш;ествует возможность ограничить область действия глобальной переменной или функции файлом, в котором они определяются. Спецификатор класса памяти static, если его применить к глобальной переменной или функции, ограничит их использование только функциями, определенными в том же самом файле. Это называется внутренним связыванием. Глобальные переменные и функции, при объявлении которых не использовался спецификатор static, имеют внешнее связывание, т. е. к ним можно обраш;аться из других
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |