
- •Оглавление
- •1.2. Свойства языков программирования
- •1.3. Основные парадигмы программирования Процедурное программирование
- •Модульное программирование
- •Абстракция данных
- •Объектно-ориентированное программирование
- •Непечатные символы
- •Тема 2 Типы данных
- •2.1. Понятие переменной и объявление переменных
- •Объявление переменных
- •Встроенные типы данных
- •Размер памяти, выделяемой под встроенные типы данных
- •2.2. Константы и перечисления Константные переменные
- •Перечисления
- •2.3. Операции и выражения
- •Мультипликативные операции
- •Операции сравнения
- •Побитовые логические операции
- •Побитовые операции
- •Комментарии
- •Оператор while(пока)
- •Оператор do/while(выполнять/пока)
- •Оператор for(цикл)
- •Оператор множественного выбора switch
- •Операторы breakиcontinue
- •Тема 4 Массивы
- •4.1.Определение, объявление и инициализация массивов
- •Объявления и инициализация массивов в программе
- •4.2. Сортировка массивов Пузырьковая сортировка
- •Сортировка вставками
- •4.3. Поиск в массивах Линейный поиск
- •Двоичный поиск
- •4.4. Многомерные массивы
- •Тема 5 Указатели Объявления и инициализация переменных указателей
- •5.1. Операции над указателями
- •5.2. Выражения и арифметические действия с указателями
- •5.3. Взаимосвязи между указателями и массивами
- •5.4. Массивы указателей
- •5.5. Динамическое выделение памяти под массивы
- •Тема 6 Функции
- •6.2. Определения функций
- •Генерация случайных чисел
- •6.3. Классы памяти и область действия Классы памяти
- •Область действия
- •6.4. Рекурсия
- •6.5. Ссылки и ссылочные параметры
- •Вызов функций по ссылке с аргументами указателями
- •6.6. Использование спецификатораconstс указателями
- •6.7. Перегрузка функций
- •Аргументы по умолчанию
- •6.8. Передача массивов в функции
- •6.9. Указатель на функцию
- •6.10. Командная строка аргументов
- •6.11 Неопределенное количество аргументов
- •Тема 7 Введение в обработку строк
- •7.1. Работа со строками в с
- •Понятие символов и строк в с
- •Функции для работы со строками
- •Определение длины строки
- •Сложение двух строк (конкатенация)
- •Добавление к исходной строке указанного количества символов.
- •Копирование строки в другую строку
- •Сравнение строк
- •Получение строки от пользователя
- •Тема 8 Работа с файлами
- •Открытие файла
- •Чтение из файла символа или строки символов
- •Запись символа или строки символов в файл
- •Смещение внутри файла
- •Значения параметра fromwhereфункцииfseek
- •Закрытие файла
- •Тема 9 Компоновка программ и препроцессор
- •9.1. Компоновка программ
- •Проблема использования общих функций и имен
- •Использование включаемых файлов
- •9.2. Препроцессор
- •Определение макросов
- •Условная компиляция
- •Дополнительные директивы препроцессора
- •Тема 10 Структуры
- •10.1. Определение структур и доступ к элементам
- •Доступ к элементам структур
- •Использование структур
- •10.2. Битовые поля
- •10.3. Объединения
- •10.4. Построение связных списков на основе структур с самоадресацией
- •Создание простого связного списка
- •Очереди
- •Деревья
- •Список рекомендуемой литературы
6.9. Указатель на функцию
Возможны только две операции с функциями [3]:
вызов,
взятие адреса.
Указатель, полученный с помощью последней операции, можно впоследствии использовать для вызова функции (рис. 6.24.)
void error(char* p) { /* ... */ }
void (*efct)(char*); // указатель на функцию
void f() {
efct = &error; // efct настроен на функцию error
(*efct)("error");} // вызов error через указатель efct
Рис. 6.24. Использование указателя на функцию
Для вызова функции с помощью указателя (efctв нашем примере) надо вначале применить операцию разыменования к указателю -*efct. Поскольку приоритет операции вызова()выше, чем приоритет разыменования*, нельзя писать просто*efct("error"). Это будет означать*(efct("error")), что является ошибкой. По той же причине скобки нужны и при описании указателя на функцию. Однако писать простоefct("error")можно, так как транслятор понимает, чтоefctявляется указателем на функцию, и создает команды, делающие вызов нужной функции.
Формальные параметры в указателях на функцию описываются так же, как и в обычных функциях. При присваивании указателю на функцию требуется точное соответствие типа функции и типа присваиваемого значения (рис. 6.25.)
void (*pf)(char*); // указатель на void(char*)
void f1(char*);
int f2(char*);
void f3(int*);
void f() {
pf = &f1; // нормально
pf = &f2; // ошибка: не тот тип возвращаемого значения
pf = &f3; // ошибка: не тот тип параметра
(*pf)("asdf"); // нормально
(*pf)(1); // ошибка: не тот тип параметра
int i = (*pf)("qwer"); // ошибка: void присваивается int
}
Рис. 6.25. Ошибки, возникающие при использовании указателя на функцию
На рис. 6.26 и 6.27 показана функция пузыковой сортировки, которая мортирует массив либо по возрастанию, либо по убыванию в зависимотис от желания пользователя. Третьим параметром функции является указатель на функцию, которая принимает два целых числа и возвращает целое.
#include <iostream>
using namespace std;
void bubble (int *, const int, int(*)(const int, const int));
int ascending(const int, const int);
int descending(const int, const int);
int main(){
const int Size = 10;
int order, a[Size] = {2,6,4,8,10,12,89,68,45,37};
cout<<"Enter order 1 or 2"<<endl;
cin>>order;
for(int i = 0; i<Size; i++)
cout<<a[i]<<'\t';
cout<<endl;
cout<<endl;
if(order==1)
bubble(a, Size, ascending);
else
bubble(a, Size, descending);
for(i = 0; i<Size; i++)
cout<<a[i]<<'\t';
cout<<endl;
return 0;}
Рис. 6.26. Функция mainпрограммы универсальной пузырьковой сортировки
void bubble (int *work, const int size, int(*compare)(int,int)) {
void swap(int *, int*);
for (int k=size-1; k>1;k--)
for(int i = 0; i<k;i++)
if((*compare)(work[i],work[i+1]))
swap(&work[i], &work[i+1]); }
void swap(int * a, int* b) {
int temp;
temp = *a;
*a = *b;
*b = temp; }
int ascending(const int a, const int b)
{
return b<a;
}
int descending(const int a, const int b)
{
return a<b;
}
Рис. 6.27. Функции сортировки, обмена и сравнения
6.10. Командная строка аргументов
Системные средства [11], на которые опирается реализация языка С, позволяют передавать командную строку аргументов или параметров начинающей выполняться программе. Когда функция mainвызывается к исполнению, она вызывается с двумя аргументами. Первый аргумент (условно называемыйargc) указывает число аргументов в командной строке, с которыми происходит обращение к программе; второй аргумент (argv) является указателем на массив символьных строк, содержащих эти аргументы, по одному в строке. Работа с такими строками - это обычное использование многоуровневых указателей.
Самую простую иллюстрацию этой возможности и необходимых при этом описаний дает программа echo, которая просто печатает в одну строку аргументы командной строки, разделяя их пробелами (рис. 6.28). Таким образом, если дана команда
echo Hello, world
то выходом будет
Hello, world
По соглашению argv[0]является именем, по которому вызывается программа, так чтоargcпо меньшей мере равен 1. В приведенном выше примереargcравен 3, аargv[0],argv[1]иargv[2]равны соответственно «echo», «Hello,» и «world». Первым фактическим аргументом являетсяargv[1], а последним -argv[argc-1]. Еслиargcравен 1, то за именем программы не следует никакой командной строки аргументов.
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
int i;
//первый вариант*********************************
for(i = 1; i < argc; i++)
cout << argv[i] << (i<argc-1) ? ' ' : '\n';
//***********************************************
//второй вариант*********************************
while (--argc > 0)
cout<<*++argv << (argc > 1) ? ' ' : '\n';
//***********************************************
return 0;
}
Рис. 6.28. Работа команды echo