- •Кетков ю.Л.
- •Раздел 5. Системные данные текстового типа 33
- •Раздел 6. Основные синтаксические конструкции языка c 46
- •Раздел 7. Указатели и ссылки 59
- •Раздел 8. Функции и их аргументы 62
- •Раздел 9. Работа с массивами. 74
- •Раздел 10. Пользовательские типы данных. 95
- •Раздел 11. Работа с файлами 104
- •Раздел 12. Библиотеки стандартных и нестандартных функций 118
- •Раздел 15. Классы. Создание новых типов данных 131
- •Раздел 16. Классы как средство создания больших программных комплексов 150
- •Раздел 17. Прерывания, события, обработка исключений 167
- •Введение
- •Раздел 1. Немного истории
- •Раздел 2. Структура программы на языке c
- •Раздел 3. Среда программирования
- •Раздел 4. Системные данные числового типа
- •4.1. Типы числовых данных и их представление в памяти эвм
- •4.1.1. Внутреннее представление целочисленных данных
- •4.1.2. Однобайтовые целочисленные данные
- •4.1.3. Двухбайтовые целочисленные данные
- •4.1.4. Четырехбайтовые целочисленные данные
- •4.1.5. Восьмибайтовые целочисленные данные
- •4.2. Внутреннее представление данных вещественного типа
- •4.3. Внешнее представление числовых констант
- •4.4. Объявление и инициализация числовых переменных
- •4.5. Ввод числовых данных по запросу программы
- •4.5.1. Потоковый ввод данных числового типа
- •4.5.2. Форматный ввод
- •4.6. Вывод числовых результатов
- •4.6.1. Форматный вывод
- •4.6.2. Потоковый вывод
- •4.7. Примеры программ вывода числовых данных
- •4.8. Операции над числовыми данными целого типа
- •4.9. Операции над числовыми данными вещественного типа
- •Раздел 5. Системные данные текстового типа
- •5.1. Символьные данные и их представление в памяти эвм
- •5.2. Строковые данные и их представление в памяти эвм
- •5.3. Ввод текстовых данных во время работы программы
- •5.3.1. Форматный ввод
- •5.3.3. Потоковый ввод
- •5.3.4. Специальные функции ввода текстовых данных
- •5.4. Вывод текстовых данных
- •5.4.1. Форматный вывод
- •5.5.2. Операции над строковыми данными
- •5.6. Управление дисплеем в текстовом режиме
- •Раздел 6. Основные синтаксические конструкции языка c
- •6.1. Заголовок функции и прототип функции
- •6.2. Объявление локальных и внешних данных
- •6.3. Оператор присваивания
- •6.4. Специальные формы оператора присваивания
- •6.5. Условный оператор
- •6.6. Оператор безусловного перехода
- •6.7. Операторы цикла
- •6.8. Дополнительные операторы управления циклом
- •6.9. Оператор выбора (переключатель)
- •6.10. Обращения к функциям
- •6.11. Комментарии в программах
- •Раздел 7. Указатели и ссылки
- •7.1. Объявление указателей
- •7.2. Операции над указателями
- •7.3. Ссылки
- •Раздел 8. Функции и их аргументы
- •8.1. Параметры-значения
- •8.2. Параметры-указатели
- •8.3. Параметры-ссылки
- •8.4. Параметры-константы
- •8.5. Параметры по умолчанию
- •8.6. Функции с переменным количеством аргументов
- •8.7. Локальные, глобальные и статические переменные
- •8.8. Возврат значения функции
- •8.9. Рекурсивные функции
- •8.10. Указатели на функцию и передача их в качестве параметров
- •8.11. "Левые" функции
- •Раздел 9. Работа с массивами.
- •9.1. Объявление и инициализация массивов.
- •9.2. Некоторые приемы обработки числовых массивов
- •9.2. Программирование задач линейной алгебры
- •9.2.1. Работа с векторами
- •9.2.2.Работа с матрицами
- •9.3. Поиск
- •9.3.1. Последовательный поиск
- •9.3.2. Двоичный поиск
- •9.4. Сортировка массивов.
- •9.4.1. Сортировка методом пузырька
- •9.4.2. Сортировка методом отбора
- •9.4.3. Сортировка методом вставки
- •9.4.4. Сортировка методом Шелла
- •9.4.5.Быстрая сортировка
- •9.5. Слияние отсортированных массивов
- •9.6. Динамические массивы.
- •Раздел 10. Пользовательские типы данных.
- •10.1. Структуры
- •10.1.1. Объявление и инициализация структур
- •10.1.2. Структуры – параметры функций
- •10.1.3.Функции, возвращающие структуры
- •10.2. Перечисления
- •10.3. Объединения
- •Раздел 11. Работа с файлами
- •11.1.Файлы в операционной системе
- •11.1. Текстовые (строковые) файлы
- •11.2. Двоичные файлы
- •11.3. Структурированные файлы
- •11.4. Форматные преобразования в оперативной памяти
- •11.5. Файловые процедуры в системе bcb
- •11.5.1. Проверка существования файла
- •11.5.2. Создание нового файла
- •11.5.3. Открытие существующего файла
- •11.5.4. Чтение из открытого файла
- •11.5.5. Запись в открытый файл
- •11.5.6. Перемещение указателя файла
- •11.5.7. Закрытие файла
- •11.5.8. Расчленение полной спецификации файла
- •11.5.9. Удаление файлов и пустых каталогов
- •11.5.10. Создание каталога
- •11.5.11. Переименование файла
- •11.5.12. Изменение расширения
- •11.5.13. Опрос атрибутов файла
- •11.5.14. Установка атрибутов файла
- •11.5.15. Опрос и изменение текущего каталога
- •11.6. Поиск файлов в каталогах
- •Раздел 12. Библиотеки стандартных и нестандартных функций
- •12.2. Организация пользовательских библиотек
- •12.3. Динамически загружаемые библиотеки
- •13.1. Препроцессор и условная компиляция
- •13.2. Компилятор bcc.Exe
- •13.3. Утилита grep.Com поиска в текстовых файлах
- •14.1. Переопределение (перегрузка) функций
- •14.2. Шаблоны функций
- •Раздел 15. Классы. Создание новых типов данных
- •15.1. Школьные дроби на базе структур
- •15.2. Школьные дроби на базе классов
- •15.3. Класс на базе объединения
- •15.4. Новые типы данных на базе перечисления
- •15.5. Встраиваемые функции
- •15.6. Переопределение операций (резюме)
- •15.8. Конструкторы и деструкторы (резюме)
- •Раздел 16. Классы как средство создания больших программных комплексов
- •16.1. Базовый и производный классы
- •16.1.1.Простое наследование
- •16.1.2. Вызов конструкторов и деструкторов при наследовании
- •16.1.3. Динамическое создание и удаление объектов
- •16.1.4. Виртуальные функции
- •16.1.5. Виртуальные деструкторы
- •16.1.6. Чистые виртуальные функции и абстрактные классы
- •16.2. Множественное наследование и виртуальные классы
- •16.3. Объектно-ориентированный подход к созданию графической системы
- •Раздел 17. Прерывания, события, обработка исключений
- •17.1. Аппаратные и программные прерывания
- •17.2. Исключения
8.7. Локальные, глобальные и статические переменные
Переменные, объявленные в теле функции, считаются локальными, принадлежащими только данной функции и недоступными для других функций. Поэтому написание функций – работа достаточно автономная, не требующая знакомства с текстами других функций. Это позволяет многим исполнителям вести параллельную разработку блоков больших программ.
К числу локальных переменных следует отнести и формальные параметры функции. Всем им оперативная память выделяется в момент вызова функции и возвращается системе после завершения работы функции. Если объявление локальной переменной совмещается с ее инициализацией, то инициализация происходит при каждом вызове функции. Этим языки C, C++ отличаются от языка Паскаль, где инициализация происходит только один раз в момент загрузки программы в память.
Если локальная переменная объявляется со спецификатором static, то такая переменная причисляется к категории статических. Память, выделенная для статических переменных, сохраняется за ними до окончания работы программы. Поэтому значения статических переменных сохраняются после выхода из функции, и при повторном обращении функция-владелец может воспользоваться предыдущим значением своей статической переменной. Для других функций значение этой статической переменной продолжает оставаться недоступным.
Переменные, объявленные за пределами всех функций, относятся к разряду глобальных. Для всех функций, расположенных в этом же программном файле, глобальные переменные общедоступны. Для "чужих" функций, находящихся в других программных файлах, такие глобальные переменные могут оказаться доступными при соблюдении двух условий:
глобальная переменная объявлена без спецификатора static;
в другом программном файле или в теле "чужой" функции эта переменная упомянута со спецификатором extern.
Глобальная переменная, объявленная со спецификатором static, доступна только для функций данного программного файла.
8.8. Возврат значения функции
Значение, которая функция возвращает вызывающей программе, указывается в операторе return. В теле функции, возвращающей значение, может находиться несколько операторов return.
8.9. Рекурсивные функции
Рекурсивные определения и рекуррентные вычислительные схемы довольно часто используются в математике. Например:
n! = n*(n-1)! //рекурсивное определение факториала
yn+1=0.5*(yn+x/yn) //итерационная формула метода Ньютона
По аналогии с такими подходами в программировании появились рекурсивные функции, которые вызывают сами себя. Кроме такой непосредственной (прямой) рекурсии возможна и косвенная рекурсия. Она имеет место, когда в цепочке функций, последовательно вызывающих друг друга, последняя функция обращается к первой. Чтобы избежать бесконечного зацикливания, в таких рекурсивных цепочках должно быть обязательно предусмотрено условие выхода.
Наиболее часто цитируемым примером рекурсивной программы является вычисление факториала:
long fact(int n)
{ if (n<2) return 1L;
return (n*fact(n-1));
}
Еще один пример, демонстрирующий вычисление n-го элемента в последовательности чисел Фибоначчи:
Fn=Fn-2+Fn-1
int Fib(int n)
{ if(n<3) return 1;
return Fib(n-2)+Fib(n-1);
}
Пример с числами Фибоначчи представляет собой крайне неэффективную по производительности программу. Дело в том, что каждый вызов функции связан с выделением участка стека, где должны храниться локальные переменные и промежуточные результаты вычислений. А функция Fib содержит в своем теле два вызова самой себя. В большинстве случаев вместо рекурсивной функции не так уж и сложно написать функцию, не содержащую рекурсии, которая и работает быстрее, и более экономно использует оперативную память. Два выше приведенных примера легко поддаются такой переделке:
long fact(int n)
{ long f=1;
for(int j=2; j<=n; j++) f=f*j;
return f;
}
//-------------------------------
int Fib(int n)
{ int j,f,f1=1,f2=1;
if(n<3) return 1;
for(j=3; j<=n; j++)
{ f=f1+f2; f1=f2; f2=f; }
return f;
}
Однако некоторые рекурсивные программы смотрятся очень неплохо. Например, функция нахождения наибольшего общего делителя двух чисел по алгоритму Евклида. Идея ее построения базируется на трех очевидных фактах:
НОД(n1,n2)=НОД(n2,n1)
НОД(0,n2)=n2
НОД(n1,n2)=НОД(n2,n3), где n3=n1(mod n2)
//Рекурсивный вариант нахождения НОД
int nod(int n1,int n2)
{ if(n1==0) return n2;
return nod(n2%n1,n1);
}
Эту функцию тоже несложно преобразовать в программу без рекурсии:
int nod(int n1,int n2)
{ int t;
m: if(n2<n1) {t=n1; n1=n2; n2=t; }
if(n1==0) return n2;
n2=n1%n2;
goto m;
}