
- •Основы программирования на языке Си.
- •Достоинства языка Си.
- •Будущее языка Си.
- •Использование языка Си.
- •Использование текстового редактора для подготовки программ.
- •Исходные и выполняемые файлы
- •Пример простой программы на языке Си
- •Структура простой программы
- •2. Лекция: Данные, символьные строки, директива #define.
- •Основные типы данных
- •Описание различных типов, переменные и константы
- •Символьные строки
- •Препроцессор языка Си
- •3. Лекция: Операции.
- •Основные операции
- •Дополнительные операции
- •Перечень операций языка Си
- •Операции, уровень приоритета которых равен 1
- •Операции, уровень приоритета которых равен 2
- •Операции, уровень приоритета которых равен 3
- •Операции, уровень приоритета которых равен 4
- •Операции, уровень приоритета которых равен 5
- •Операции, уровень приоритета которых равно 6
- •Операции, уровень приоритета которых равен 7
- •Операция, уровень приоритета которой равен 8
- •Операция, уровень приоритета которой равен 9
- •Операция, уровень приоритета которой равен 10
- •Операция, уровень приоритета которой равен 11
- •Операция, уровень приоритета которой равен 12
- •Операция, уровень приоритета которой равен 13
- •Операция, уровень приоритета которой равен 14
- •Операция, уровень приоритета которой равен 15
- •Примеры простых задач
- •4. Лекция: Операторы.
- •Выражения
- •Простейшие выражения
- •Операторы
- •Составные операторы
- •Оператор цикла while
- •10 Км. В последующие дни он проезжал со скоростью,
- •Изучение и использование функций printf( ) и scanf( )
- •Применение функции scanf( )
- •Подведем итог.
- •5. Лекция: преобразование типов.
- •Эквивалентность типов
- •Преобразование типов
- •Разбор программы
- •Операция приведения
- •Неявное преобразование типа
- •Арифметические преобразования
- •Явные преобразования типов
- •Синтаксис типов
- •6. Лекция: функции и переключение ввода-вывода
- •Ввод и вывод одного символа
- •Чтение одной строки
- •Чтение файла
- •Переключение и работа с файлами
- •7. Лекция: Выбор вариантов.
- •Выбор вариантов
- •Оператор if
- •Расширение оператора if
- •Операции отношения
- •Логические операции
- •Операция условия: ?:
- •Множественный выбор
- •8. Лекция: Циклы и другие управляющие средства. Структурное программирование.
- •Структурное программирование
- •Цикл с предусловием
- •Цикл со счетчиком
- •Цикл с постусловием
- •Другие управляющие операторы
- •9. Лекция: Функции.
- •Создание и использование функций
- •Аргументы функции
- •Возвращение значений
- •Локальные переменные
- •Нахождение адресов
- •Указатели, первое знакомство
- •Функции с переменным количеством аргументов
- •10. Лекция: Классы памяти и разработка программ.
- •Классы памяти и область действия
- •Автоматические переменные
- •Внешние переменные
- •Статические переменные
- •Внешние статические переменные
- •Регистровые переменные
- •11. Лекция: Препроцессор языка Си.
- •Общие сведения
- •Символические константы: #define
- •Использование аргументов с #define
- •Макроопределение или функция?
- •Включение файла: #include
- •Условная компиляция
- •12. Лекция: Массивы и указатели.
- •Указатели и массивы
- •Массивы
- •Указатели
- •Динамические объекты
- •Создание динамических объектов
- •Доступ к динамическим объектам
- •Связь между указателями и массивами
- •Инициализация массивов и классы памяти
- •Функции, массивы и указатели
- •Операции с указателями
- •13. Лекция: Символьные строки и функции над ними.
- •Строковые константы
- •Массивы символьных строк и их инициализация
- •Массив и указатель: различия
- •Указатели и строки
- •Ввод-вывод строк
- •Обработка строк
- •14. Лекция: Структуры.
- •Определение структурных переменных
- •Доступ к компонентам структуры
- •Поля битов в структурах
- •Объединения
- •Перечисления
- •Переменные структуры
- •Указатели и структуры
- •Массив структур
- •Переименование типов
- •15. Лекция: Библиотека языка Си и файлы ввода-вывода.
- •Стандартные библиотечные функции
- •Связь с файлами
- •Текстовые файлы с буферизацией
- •Распределение памяти
- •16. Лекция: Функции в примерах.
- •Функция получения случайных чисел
- •Поиск узлов из простых чисел
- •Матрица инцидентности
- •Структуры данных
- •Все операции со стеком
Символьные строки
Символьная строка- это последовательность символов, возможно пустая (""). Рассмотрим пример:
"Большой спрос на образование в области
информационных дисциплин объясняется не только
популярностью компьютеров в современном обществе,
но и реальной пользой от их применения."
Кавычки не являются частью строки. Они вводятся только для того, чтобы отметить ее начало и конец. В языке Си нет специального типа, который можно было бы использовать для описания строк. Вместо этого строки представляются в виде "набора" элементов типа char. Это означает, что символы в строке можно представить расположенными в соседних ячейках памяти - по одному символу в ячейке. Символ \0 в языке Си используется для того, чтобы отмечать конец строки. Нуль-символ не выводится на печать и в таблице кода ASCII (American Standard Code for Information Interchange) имеет номер 0. Наличие нуль-символа означает, что количество ячеек массива символов должно быть на одну больше, чем число символов строки. Массив можно представить как совокупность нескольких ячеек памяти, объединенных в одну строку.Массив- это упорядоченная последовательность элементов данных одного типа. В нашем примере мы создали массив из 177 ячеек памяти, в каждую из которых можно поместить один символ типа char. Это можно сделать с помощью оператора описания:
char String[177];
Квадратные скобки указывают, что переменная String- массив из177элементов, а char задает тип каждого элемента. Длину строки в символах (без завершающего символа) определяет функцияstrlen( ). Обращение к ней в нашем примере выглядит так:
strlen(String);
Результат - целое число.
Препроцессор языка Си
Вернемся к константам. Чтобы ввести ту или иную константу в программу, нужно указать ее фактическое значение, как было сказано выше. Можно использовать вместо этого "символические константы" и позволить компилятору заменить символические константы числами. Как можно создать такую константу? Можно это сделать так:
float cost = 0.0012;
Такой способ задания констант в больших программах неэкономичен. В Си имеется другой, лучший способ. Этот способ реализуется с помощью препроцессора языка Си. Препроцессор дает возможность задавать константы. Для этого в начало программы нужно добавить строку, аналогичную следующей:
#define COST 0.0012
При компиляции программы каждый раз, когда появится переменная COST, она будет заменяться величиной0.0012. Такой процесс называется подстановкой во время компиляции. Замечание по поводу формата: сначала идет ключевое слово#define(оно должно начинаться с самой левой позиции), потом идет символическое имя константы, а затем ее величина. Символ "точка с запятой"не используется, потому что это не оператор языка Си.
Если в качестве первого символа в строке программы используется символ #, то эта строка являетсякомандной строкой препроцессора(макропроцессора). Командная строка препроцессора заканчивается символом перевода на новую строку. Если непосредственно перед концом строки поставить символ обратной косой (\), то командная строка будет продолжаться на следующей строке программы.
Препроцессор используется для обработки текста программы до этапа ее компиляции. Обычно препроцессоры служили средством расширения языков с целью обеспечения дополнительных возможностей. Несмотря на бесчисленное множество препроцессоров, созданных для расширения возможностей языков программирования, все они были нестандартными. Для некоторых языков, например для языков общего назначения ПЛ/1 и Си, препроцессоры поставлялись как часть их стандартной среды. Препроцессор для языка Си обеспечивает средства для определения макросов, определения констант, включения файлов и условную компиляцию. Препроцессор языка Си вызывается автоматически при обращении к компилятору. Программа может быть обработана только препроцессором без компиляции, если в командессуказать ключ-Е:
cc -E имя_файла
Результат работы препроцессора помещается в поток стандартного вывода stdout. Обработка программы препроцессором без компиляции позволяет программисту проанализировать действие определений препроцессора и макровызовов.
! Символическую константу после #define лучше писать прописными буквами. В процессе использования языка Си выработалась традиция писать константы большими буквами. Если при просмотре программы встречается имя, написанное прописными буквами, сразу становится ясно, что это константа, а не переменная. Давайте не нарушать традицию!
Директиву #defineможно использовать для определения символьных и строковых констант. В первом случае необходимо использовать "апостроф", а во втором кавычки.
Например,
#define NULL '\0'
#define USA '$'
#define RUSSIA "Рубль"
#undef USA
Команда #undef USAотменяет предыдущее определение для идентификатораUSA. Через команду#defineможно задавать выражения -макросы, которые вычисляются и при компиляции подставляются в программу. Воизбежании ошибок при вычислении выражений макроопределения необходимо заключать в скобки:
#define идентификатор1 (идентификатор2,_) строка
Пример:
#define abs(A) (((A)>0) ? (A): - (A))
Каждое вхождение выражения abs(arg)в тексте программы заменяется на((arg)>0) ? (arg): -(arg)), причем параметр макроопределения A заменяется на arg.
Пpимер:
#define nmem(P,N)\
(P)->p_mem[N].u_long
Символ \ продолжает макроопределение на вторую строку. Это макроопределение уменьшает сложность выражения, описывающего массив объединений внутри структуры.
Макроопределенияпрепроцессора языка Си имеют две формы -простуюипараметризованную,
#define идентификатор строка_замены
#define идентификатор(x1,x2,_,xn) строка_замены
где строка_заменыможет содержать идентификаторы, ключевые слова, разделители, такие как круглая или прямоугольная скобка, или строки знаков, не содержащие каких-либо разделителей.
Замечание.
Командная строка #includeможет встречаться в любом месте программы, но обычно все включения размещаются в начале исходного текста:
#include <имя_файла>
Пример:
#include <math.h>
Препроцессор заменяет эту строку содержимым файла math.h. Угловые скобки обозначают, что файлmath.hбудет взят из некоторого стандартного каталога, обычно это/usr/include. Текущий каталог не просматривается:
#include "имя_файла"
Пример:
#include "ABC"
Препроцессор заменяет эту строку содержимым файла ABC. Так как имя файла заключено в кавычки, то поиск производится в текущем каталоге, в котором содержится основной файл исходного текста. Если в текущем каталоге данного файла нет, то поиск производится в каталогах, определенных именем пути в опции-iпрепроцессора. Если и там файла нет, то просматривается стандартный каталог.
Командные строки препроцессора используются для условной компиляции различных частей исходного текста в зависимости от внешних условий. Условной компиляциейназывается выборочная компиляция только тех частей программы, которые удовлетворяют определенным условиям. Например, можно скомпилировать только те части программы, которые необходимы для конкретной версии системы.
Условная компиляцияобладает следующимидостоинствами:
Обеспечивается средство параметризации во время компиляции. Например, такая возможность может быть использована для генерации программ с различной структурой.
Обеспечивается эффективное использование оперативной памяти, поскольку во время выполнения нет необходимости держать в памяти неиспользуемые коды программы.
Обеспечивается возможность принятия решений во время компиляции, а не во время выполнения. Часто это оказывается более эффективным подходом.
Для условной компиляции используется инструкция препроцессора if. Она имеет две формы - с частьюelseи без нее:
#if - заголовок
текстовые строки для случая "истина"
#endif
и
#if- заголовок
текстовые строки для случая "истина"
#else
текстовые строки для случая "ложь"
#endif
где if- заголовок является управляющей строкой препроцессора, а текстовые строки могут содержать произвольный текст. Управляющая строка препроцессораif-заголовка содержит условие, на основе анализа которого производится выбор соответствующихтекстовых строк:
#if константное_выражение
Пример:
#ifdef ABC
Истина, если идентификатор ABCопределен ранее
командой #define.
#ifndefидентификатор
Пример:
#ifndef ABC
Истина, если идентификатор ABC не определен
в настоящий момент.
#else
...
#endif
Если предшествующие проверки #if,#ifdefили#ifndefдают значение Истина, то строки от#elseдо#endifигнорируются при компиляции. Если эти проверки дают значение Ложь, то строки от проверки до#else, а при отсутствии#else- до#endif, игнорируются. Команда#endifобозначает конец условной компиляции.
Пример:
#ifdef DEBUG
fprintf (stderr, "location. X=%d\n",x);
#endif
При помощи команд препроцессора можно изменить номертекущейстрокиилиимякомпилируемого файла:
#line целая_константа "имя_файла"
Пример:
#line 20 "ABC"
Препроцессор изменяет номер текущей строки и имя компилируемого файла. Имя файла может быть опущено.
Замечание.
Хотя препроцессоры и расширяют возможности языков программирования, их использование не лишено недостатков: использование препроцессоров требует дополнительного просмотра текста программы и, как следствие, добавочного времени.