Структура программы. Скалярные типы данных. Выражения и присваивания цель: Изучить категории типов данных, виды выражений и операций и работу с ними на языке Си. Общие сведения
Вид материала | Лабораторная работа |
СодержаниеЛабораторная работа № 10 Практические задания |
- Алгоритм и программа поиска минимального и максимального элементов в массиве. Задача, 17.73kb.
- Понятие типа данных. Переменные и константы. Основные типы данных в языке Си: общая, 143.1kb.
- Структура программы. Часть Структуры данных. 24. Классификация структур данных. Операции, 41.26kb.
- Курс за второй семестр. Абстрактные типы данных, 687.76kb.
- Программа дисциплины программирование на языке С++ для направления 080700. 62 «Бизнес-информатика», 131.2kb.
- Основы Pascal. Типы данных. Структура программы на языке Pascal, 3515.8kb.
- Лабораторная работа №4 Тема : Структурный тип данных в языке С++, 112.14kb.
- Практическая работа № «Создание базы данных», 21.96kb.
- Структура программы. Описание типов данных. Любая программа,все равно на каком языке, 611.52kb.
- Лекция Выражения. Операции в выражениях Построение выражений. Операции и их приоритеты., 271.62kb.
Лабораторная работа № 10
ПРАВИЛА ИСПОЛЬЗОВАНИЯ ДИРЕКТИВ
ПРЕПРОЦЕССОРА
Цель: Изучение основных правил использования директив препроцессора Си.
Общие сведения
В интегрированную среду подготовки программ на Си++ или в компилятор языка как обязательный компонент входит препроцессор. Назначение препроцессора - обработка исходного текста программы при ее компиляции. Препроцессорная обработка в соответствии с требованиями стандарта языка Си++ включает несколько стадий, выполняемых последовательно. Конкретная реализация транслятора может разъединять несколько стадий, но результат должен быть таким, как если бы они выполнялись последовательно:
- Все системно зависимые обозначения (например, системно зависимый индикатор конца строки) перекодируются в стандартные коды;
- Каждая пара из символов '\' и "конец строки" убираются, и тем самым следующая строка исходного файла присоединяется к строке, в которой находилась эта пара символов;
- В тексте распознаются директивы препроцессора, а каждый комментарий заменяется одним символом пустого промежутка.
- Выполняются директивы препроцессора и производятся макроподстановки;
- ЕSC-последовательности в символьных константах и символьных строках, например, '\n' заменяются на их эквиваленты (на соответствующие числовые коды);
- Смежные символьные строки конкатенируются, т. е. соединяются в одну строку.
Знакомство с перечисленными задачами препроцессорной обработки объясняет некоторые соглашения синтаксиса языка. Например, становится понятным смысл утверждений: каждая символьная строка может быть перенесена в файле на следующую строку, если использовать символ '\’, или две символьные строки, записанные рядом, воспринимаются как одна строка.
Рассмотрим подробно стадию обработки директив препроцессора. При ее выполнении возможны следующие действия:
- замена идентификаторов (обозначений) заранее подготовленными последовательностями символов;
- включение в программу текстов из указанных файлов;
- исключение из программы отдельных частей ее текста (условная компиляция);
- макроподстановка, т. е. замена обозначения параметризованным текстом, формируемым препроцессором с учетом конкретных параметров (аргументов).
Для управления препроцессором, т. е. для задания нужных действий, используются команды (директивы) препроцессора, каждая из которых помещается на отдельной строке и начинается с символа #. Определены следующие препроцессорные директивы: #defune, #include, #undef, #if, #ifdef, #ifndef, #else, #endif, #elif, #line, #error, #pragma, #.
Директива #define имеет несколько модификаций. Они предусматривают определение макросов или препроцессорных идентификаторов, каждому из которых ставится в соответствие некоторая символьная последовательность. В последующем тексте программы препроцессорные идентификаторы заменяются на заранее запланированные последовательности символов.
Директива #include позволяет включать в текст программы текст из выбранного файла.
Директива #undef отменяет действие команды #define, которая определила до этого имя препроцессорного идентификатора.
Директива #if и ее модификации #ifdef, #ifndef совместно с директивами #else, #endif, #elif позволяют организовать условную обработку текста программы. Условность состоит в том, что компилируется не весь текст, а только те его части, которые так или иначе выделены с помощью перечисленных директив.
Директива #line позволяет управлять нумерацией строк в файле с программой. Имя файла и начальный номер строки указываются непосредственно в директиве #line.
Директива #еrror позволяет задать текст диагностического сообщения, которое выводится при возникновении ошибок.
Директива #pragma вызывает действия, зависящие от реализации.
Директива # ничего не вызывает, т. к. является пустой директивой, т. е. не дает никакого эффекта и всегда игнорируется.
Рассмотрим возможности перечисленных команд при решении типичных задач, поручаемых препроцессору.
Для замены идентификатора заранее подготовленной последовательностью символов используется следующая директива (обратите внимание на пробелы): #define идентификатор строка замещения.
Директива может размещаться в любом месте обрабатываемого текста, а ее действие в обычном случае распространяется от точки замещения до конца текста. Директива, во-первых, определяет идентификатор как процессорный. В результате обработки все вхождения определенного командой #define идентификатора в текст программы вменяются строкой замещения, окончанием которой обычно служит признак конца той строки, где размещена команда #define. Символы пробелов, помещенные в начале и в конце строки замещения, в подстановке не используются. Например:
Исходный текст Результат препроцессорной обработки
#define begin {
#define end }
void main() void main()
begin {
операторы операторы
end }
В данном случае программист решил использовать в качестве операторных скобок идентификаторы begin, end.
Компилятор языка Си++ не может обрабатывать таких скобок, и поэтому до компиляции препроцессор заменяет все вхождения этих идентификаторов стандартными скобками { и }. Соответствующие указания программист дал препроцессору с помощью директив #define.
Директиву #undef удобно использовать при разработке больших программ, когда они собираются из отдельных "кусков текста", написанных в разное время или разными программистами. В этом случае могут встретиться одинаковые обозначения разных объектов. Чтобы не изменять исходных файлов, включаемый текст можно "обрамлять" подходящими директивами #define - #undef и тем самым устранять возможные ошибки. Приведем пример:
…
А = 10; // Основной текст
…
#define A X
…
А = 5; // Включенный текст
…
#undef A
…
В = А; // Основной текст
…
При выполнении программы В примет значение 10, несмотря на наличие оператора присваивания А = 5 во включенном тексте.
Для включения текста из файла используется команда #include, имеющая две формы записи:
#include <имя файла> // Имя в угловых скобках
#include "имя файла" // Имя в кавычках.
Если имя_файла – в угловых скобках, то препроцессор разыскивает файл в стандартных системных каталогах. Если имя_файла заключено в кавычки, то вначале препроцессор просматривает текущий каталог пользователя и только затем обращается к просмотру стандартных системных каталогов.
Начиная работать с языком Си++, пользователь сразу же сталкивается с необходимостью использования в программах средств ввода-вывода. Для этого в начале текста программы помещают директиву #include
Выполняя эту директиву, препроцессор включает в программу средства связи с библиотекой ввода-вывода. Поиск файла iostream.h ведется в стандартных системных каталогах. По принятому соглашению суффикс .h приписывается тем файлам, которые нужно помещать в заголовке программы, т. е. до исполняемых операторов.
Кроме такого, в некоторой степени стандартного файла, каким является iostream.h, в заголовок программы могут быть включены любые другие файлы (стандартные или подготовленные специально).
Заголовочные файлы оказываются весьма эффективным средством при модульной разработке крупных программ, когда связь между модулями, размещаемыми в разных файлах, реализуется не только с помощью параметров, но и через внешние объекты, глобальные для нескольких или всех модулей. Описания таких внешних объектов (переменных, массивов, структур и т. п.) помещаются в одном файле, который с помощью директив #include включается во все модули, где необходимы внешние объекты. В тот же файл можно включить и директиву подключения библиотеки функций ввода-вывода. Заголовочный файл может быть, например, таким:
#include
extern int ii, jj, 11; // Целые внешние переменные
extern float AA, BB; // Вещественные внешние переменные
В практике программирования на Си++ обычна и обратная ситуация. Если в программе используется несколько функций, то иногда удобно текст каждой из них хранить в отдельном файле. При подготовке программы пользователь включает в нее тексты используемых функций с помощью команд #include.
Практические задания:
- Разработать функцию зануления столбца двумерного массива. Занулить 3 столбца. Результат вывести на печать.
- Разработать функцию зануления строки двумерного массива. Занулить 3 произвольные строки. Результат вывести на печать.
- Разработать функцию очистки (зануления) двумерного массива. Занулить два массива. Результат вывести на печать.
- Разработать функцию, позволяющую инвертировать каждый столбец двумерного массива целых чисел. Обработать два массива. Результат вывести на печать.
- Разработать функцию, которая меняет местами содержимое старшего и младшего байтов каждого элемента двумерного массива. Ввести два двумерных массива разной длины. Результаты вывести на печать.
- Заполнить 2 двумерных массива разной длины символами. Написать функцию, которая ставит символ пробела в старшем байте каждого слова массива. Обработать 2 массива. Результаты вывести на печать.
- Разработать функцию поэлементного суммирования двух строк массива в одну. Ввести массив. Сложить два раза по две строки. Вывести на печать.
- Разработать функцию поэлементного суммирования двух столбцов двумерного массива. Просуммировать два раза по два столбца. Результат вывести на печать.
- Разработать функцию, позволяющую поменять местами две произвольные столбца двумерного массива. Ввести массив. Поменять два раза по два столбца. Результат вывести на печать.
- Разработать функцию, позволяющую поменять местами две произвольные строки двухмерного массива. Ввести массив. Поменять два раза по две строки. Результат вывести на печать.
- Разработать функцию выделения произвольного столбца в двумерном массиве. Ввести массив и выделить в нем два произвольных столбца. Результат вывести на печать.
- Разработать функцию поэлементного умножения массива на константу. Результат вывести на печать.
- Разработать функцию поэлементного сложения двух двумерных массивов одинаковой длины в третий. Ввести шесть двумерных массивов. Результат вычислений вывести на печать.
- Разработать функцию выделения произвольной строки из двумерного массива. Ввести двумерный массив. Выделить и вывести две строки. Результат вывести на печать.
- Разработать функцию суммирования элементов двумерного массива произвольной длины. Ввести два массива разной длины. Результат вычислений вывести на печать.
- Разработать функцию, которая переводит десятичное число в двоичное. Ввести пять чисел. Результат вывести на печать.
- Разработать функцию перевода десятичного числа в шестнадцатеричное представление. Ввести пять чисел. Результат вывести на печать.
- Разработать функцию перевода двоичного числа в шестнадцатеричное. Ввести десять чисел. Результат вывести на печать.
- Разработать функцию перевода двоичного числа в восьмеричное представление. Ввести восемь чисел. Результат вывести на печать.
- Разработать функцию перевода десятичного числа в восьмеричное представление. Ввести десять чисел. Результат вывести на печать.
Лабораторная работа № 11