- •Алфавит.
- •Объявления и определения
- •Структура и компоненты простой программы
- •Текст программы и препроцессор.
- •Структура программы.
- •Функция форматированного вывода.
- •Программы печати предельных констант.
- •Применимость вещественных данных.
- •Выделение лексем из текста программы.
- •2.2. Элементарные средства программирования Деление операторов языка Си на группы.
- •Программа оценки машинного нуля.
- •Трассировочная таблица
- •Переключатели
- •Ввод данных.
- •Вычисление объема цилиндра.
- •Операторы цикла
- •Три формы операторов цикла.
- •Приближенное значение экспоненты.
- •Оператор break.
- •Сумма отрезка степенного ряда.
- •Оператор continue.
- •Суммирование положительных чисел.
- •2.4. Массивы и вложение операторов цикла Массивы и переменные с индексами.
- •Вычисление среднего и дисперсии.
- •Упорядочение в одномерных массивах.
- •Инициализация массивов.
- •Моделирование многомерных массивов.
- •Ввод и вывод
- •7.1. Потоковый ввод-вывод
- •7.1.1. Открытие и закрытие потока
- •7.1.2. Стандартные файлы и функции для работы с ними
- •Ввод-вывод отдельных символов.
- •Ввод-вывод строк.
- •Форматный ввод-вывод.
- •Спецификаторы форматной строки для функции форматного вывода
- •Спецификаторы форматной строки для функции форматного ввода
- •Работа с файлами на диске
- •Двоичный (бинарный) режим обмена с файлами.
- •Строковый обмен с файлами.
- •Позиционирование в потоке.
- •Трехъязычный словарь "Цифры
- •7.2. Ввод-вывод нижнего уровня
- •7.2.1. Открытие / закрытие файла
- •7.2.2. Чтение и запись данных
- •7.2.3. Произвольный доступ к файлу
- •Теоретические положения Управление экраном в текстовом режиме в ms dos
- •Основные функции работы в текстовом режиме
- •2.5. Функции Определение функций.
- •Функция для вычисления объема цилиндра.
- •Функция для вычисления скалярного произведения векторов.
- •Обращение к функции и ее прототип.
- •Вычисление объема цилиндра
- •Вычисление площади треугольника.
- •Скалярное произведение векторов.
- •Препроцессорные средства
- •Глава 6. Структуры и объединения
- •6.1. Структурные типы и структуры Производные типы.
- •Структурный тип.
- •Определение структур.
- •Выделение памяти для структур.
- •Инициализация и присваивание структур.
- •Доступ к элементам структур.
- •Модули:
- •Некоторые понятия:
1.1. Языки программирования С и C++
Триумфальное шествие языка С началось с появления его компилятора для персональных компьютеров (ПК). Всего несколько лет назад этот язык высокого уровня был известен лишь узкому кругу специалистов. Тем не менее этот неизвестный язык, оставив позади модные языки, получил широкое распространение. Большинство популярных коммерческих программ написаны, если не исключительно, то по меньшей мере частично на языке С. Например, dBase, Word, PageMaker, PC-DOS или Sidekick.
В противоположность другим языкам высокого уровня, таким как Pascal или Basic, которые разрабатывались в университетах как учебные языки, язык С возник из реальных проблем и предназначался для решения конкретных практических задач. Его создателям — Брайану Кернигану (Brian W. Kernighan) и Деннису Ритчи (Dennis M. Ritchie) — был необходим язык для системного программирования, который создавал бы быстродействующий и компактный код и, кроме того, был бы мобильным настолько, насколько это возможно. Язык должен был обладать возможностями действительно языка высокого уровня, поскольку выяснилось, что применение языков низкого уровня (Ассемблера) при разработке больших программных проектов приводит к нечитабельности программ, которые к тому же являются абсолютно немобильными. Поставленная задача создателями языка решена чрезвычайно успешно.
Расширение языка С в соответствии с объектно-ориентированной концепцией реализовано Бьорном Страуструпом (Bjarne Stroustrup). Именно расширение, потому что совместимость с С является отличительной чертой C++. Промежуточный вариант между С и C++ назывался «С с классами». В 1985 году появилась версия, с помощью которой стала возможна реализация объектно-ориентированного подхода в программировании. Эта версия получила известность под именем C++. За прошедшее время язык C++ принял законченную форму и стал столь же совершенным, как и С. Одним из основных принципов, лежащих в основе C++, является его практически полная совместимость с С, которая существенно облегчила переход программистов, работавших на языке С, к объектно-ориентированному программированию и гарантировала применимость существующих С-кодов.
С другой стороны, C++ можно рассматривать как определенную версию С в противоположность таким полностью объектно-ориентированным языкам, как Модула или Смоллток. Поэтому программирование на C++ не может автоматически приравниваться к объектно-ориентированному программированию.
1.2. Отличительные признаки
Язык С с самого начала создавался как язык высокого уровня для системного программирования и предназначался, главным образом, для развития операционных систем. Поскольку С разрабатывался как встроенное системное средство, то создаваемый им код должен был достаточно просто компилироваться и иметь высокое быстродействие. Таким образом, появился язык, который отличался:
-
небольшим количеством элементов языка;
-
высокой скоростью выполнения написанных на нем программ;
-
поддержкой модульного программирования;
-
хорошей мобильностью наряду с возможностью работы на «нижнем уровне» (с компонентами аппаратной среды).
С развитием вычислительной техники время вычислений становится все дешевле, а затраты на программирование возрастают.
Лексема - единица текста программы, которая при компиляции воспринимается как единое целое и по смыслу не может быть разделена на более мелкие элементы.
Алфавит – совокупность допустимых в языке символов или групп символов.
В языке Турбо Паскаль все компоненты формируются из множества символов стандарта ASCII, которые задаются кодами от 0 до 255.
Элементы алфавита:
Алфавит.
В алфавит языка Си входят:
• прописные и строчные буквы латинского алфавита (A,B,...,Z, a, b,..., z)
• цифры: 0,1,2,3,4,5,6,7,8,9
• специальные знаки: “ , {} | [] ( ) + - / % \ ; ‘ . : ? < = > _ & * # ~ ^
• неизображаемые символы ("обобщенные пробельные символы"), используемые для отделения лексем друг от друга (например, пробел, табуляция, переход на новую строку).
В комментариях, строках и символьных константах могут использоваться и другие литеры (например, русские буквы).
Комментарий формируется как последовательность знаков (символов), ограниченная слева знаками /*, а справа - знаками */. Например:
Объявления и определения
Главная задача любой программы состоит в обработке данных. Во время выполнения программы эти данные размещаются в различных местах оперативной памяти. Для корректного использования данных без указания адресов в явном виде применяют переменные.
Переменные представляют собой имена областей памяти, в которых находятся данные определённых типов. С помощью таких имен можно записывать (считывать) данные в область (из области) памяти.
В зависимости от вида данных для них могут применяться переменные различных типов. Типы данных определяют внутреннее представление данных в вычислительных машинах; диапазон значений, которые может принимать переменная, а также операции, в которых могут использоваться переменные указанного типа.
При разработке программы необходимо объявить используемые в ней элементы (переменные, функции, структурированные типы и т.д.) и определиться в правилах. Понятия «объявление» и «определение» часто употребляются как синонимы, хотя они означают различные процедуры.
Объявление:
-
Объявление означает задание компилятору имен (идентификаторов) переменных, функций, классов, структурированных типов или меток.
-
С помощью объявления переменной задается её тип, класс памяти и область видимости идентификатора.
-
Объявление резервирует память.
-
Идентификатор может неоднократно объявляться в рамках своей области видимости, при этом все предыдущие объявления не учитываются.
Структура и компоненты простой программы
Ранее были рассмотрены лексемы языка, способы определения констант и переменных, правила записи и вычисления выражений. Несколько слов было сказано об операции присваивания, об операторе присваивания и о том, что каждое выражение превращается в оператор, если в конце выражения находится разделитель "точка с запятой". Сейчас перейдем собственно к программированию, т.е. рассмотрим операторы, введем элементарные средства ввода-вывода, опишем структуру однофайловой программы и на несложных примерах вычислительного характера продемонстрируем особенности программирования на языке Си.
Текст программы и препроцессор.
Текст программы и препроцессор. Каждая программа на языке Си есть последовательность препроцессорных директив, описаний и определений глобальных объектов и функций. Препроцессорные директивы (#include и #define) управляют преобразованием текста программы до ее компиляции. Определения вводят функции и объекты. Объекты необходимы для представления в программе обрабатываемых данных. Функции определяют потенциально возможные действия программы. Описания уведомляют компилятор о свойствах и именах тех объектов и функций, которые определены в других частях программы (например, ниже по ее тексту или в другом файле).
Программа на языке Си должна быть оформлена в виде одного или нескольких текстовых файлов. Текстовый файл разбит на строки. В конце каждой строки есть признак ее окончания (плюс управляющий символ перехода к началу новой строки). Просматривая текстовый файл на экране дисплея, мы видим последовательность строк, причем признаки окончания строк невидимы, но по ним производится разбивка текста редактором.
Определения и описания программы на языке Си могут размещаться в строках текстового файла достаточно произвольно (в свободном формате.) Для препроцессорных директив существуют ограничения. Во-первых, препроцессорная директива обычно размещается в одной строке, т.е. признаком ее окончания является признак конца строки текста программы. Во-вторых, символ '#', вводящий каждую директиву препроцессора, должен быть первым отличным от пробела символом в строке с препроцессорной директивой
Подробному изучению возможностей препроцессора и всех его директив будет далее. Сейчас достаточно рассмотреть только основные принципы работы препроцессора и изложить общую схему подготовки исполняемого модуля программы, написанной на языке Си. Исходная программа, подготовленная на языке Си в виде текстового файла, проходит три обязательных этапа обработки (рис. 2.1):
• препроцессорное преобразование текста;
• компиляция;
• компоновка (редактирование связей или сборка).
Рис. 2.1. Схема подготовки исполняемой программы
Только после успешного завершения всех перечисленных этапов формируется исполняемый машинный код программы.
Задача препроцессора - преобразование текста программы до ее компиляции. Правила препроцессорной обработки определяет программист с помощью директив препроцессора. Каждая препроцессорная директива начинается с символа '#'. В этой главе нам будет достаточно двух директив:
#include и #define.
Препроцессор "сканирует" исходный текст программы в поиске строк, начинающихся с символа '#'. Такие строки воспринимаются препроцессором как команды (директивы), которые определяют действия по преобразованию текста. #define указывает правила замены в тексте.
# include определяет, какие текстовые файлы нужно включить в этом месте текста программы.
Директива #include <...> предназначена для включения в текст программы текста файла из каталога "заголовочных файлов", поставляемых вместе со стандартными библиотеками компилятора. Каждая библиотечная функция, определенная стандартом языка Си, имеет соответствующее описание (прототип библиотечной функции плюс определения типов, переменных, макроопределений и констант) в одном из заголовочных файлов. Список заголовочных файлов для стандартных библиотек определен стандартом языка.
Важно понимать, что употребление в программе препроцессорной директивы
#include < имя_заголовочного_файла >
не подключает к программе соответствующую стандартную библиотеку. Препроцессорная обработка выполняется на уровне исходного текста программы. Директива #include только позволяет вставить в текст программы описания из указанного заголовочного файла. Подключение к программе кодов библиотечных функций (см. рис. 2.1) осуществляется только на этапе редактирования связей (этап компоновки), т.е. после компиляции, когда уже получен машинный код программы. Доступ к кодам библиотечных функций нужен только на этапе компоновки. Именно поэтому компилировать программу и устранять синтаксические ошибки в ее тексте можно без стандартной библиотеки, но обязательно с заголовочными файлами.
Здесь следует отметить еще одну важную особенность. Хотя в заголовочных файлах содержатся описания всех стандартных функций, в код программы включаются только те функции, которые используются в программе. Выбор нужных функций выполняет компоновщик на этапе, называемом "редактирование связей".
Термин "заголовочный файл" (header file) в применении к файлам, содержащим описания библиотечных функций стандартных библиотек, не случаен. Он предполагает включение этих файлов именно в начало программы. Мы настоятельно рекомендуем, чтобы до обращения к любой функции она была определена или описана в том же файле, где помещен текст программы. Описание или определения функций должны быть "выше" по тексту, чем вызовы функций. Именно поэтому заголовочные файлы нужно помещать в начале текста программы, т.е. заведомо раньше обращений к соответствующим библиотечным функциям.
Хотя заголовочный файл может быть включен в программу не в ее начале, а непосредственно перед обращением к нужной библиотечной функции, такое размещение директив #include <...> не рекомендуется.