- •ПРОГРАММИРОВАНИЕ НА ЯЗЫКАХ С И С++
- •СОДЕРЖАНИЕ
- •ВВЕДЕНИЕ
- •1. ЛЕКСИКА ЯЗЫКА C
- •1.1. РАЗДЕЛИТЕЛИ
- •1.2. КОММЕНТАРИИ
- •2. ДАННЫЕ И ОПЕРАЦИИ
- •2.1. БАЗОВЫЕ ТИПЫ ДАННЫХ
- •Наименование
- •Диапазон
- •2.2. КОНСТАНТЫ
- •Целые константы
- •Константы с плавающей точкой
- •Символьные константы
- •2.3. ОПРЕДЕЛЕНИЕ ПЕРЕМЕННЫХ И ТИПИЗИРОВАННЫХ КОНСТАНТ
- •2.4. ОДНОМЕРНЫЙ МАССИВ
- •2.5. СТРОКИ, СТРОКОВЫЕ КОНСТАНТЫ
- •2.6. УКАЗАТЕЛИ
- •2.7. ПЕРЕИМЕНОВАНИЯ ТИПОВ
- •2.8. СТРУКТУРЫ
- •2.9. МАССИВЫ СТРУКТУР
- •2.10. МНОГОМЕРНЫЕ МАССИВЫ
- •2.11. ОБЪЕДИНЕНИЕ
- •2.12. ПЕРЕЧИСЛЕНИЕ
- •2.13. БИТОВОЕ ПОЛЕ ( ЗАПИСЬ )
- •3. ОПЕРАЦИИ И ВЫРАЖЕНИЯ
- •3.1. АРИФМЕТИЧЕСКИЕ ОПЕРАЦИИ
- •3.2. ОПЕРАЦИИ СРАВНЕНИЯ
- •3.3. ЛОГИЧЕСКИЕ ОПЕРАЦИИ
- •3.4. ПОБИТОВЫЕ (ПОРАЗРЯДНЫЕ) ОПЕРАЦИИ
- •3.5. ОПЕРАЦИИ ПРИСВАИВАНИЯ
- •3.6. АДРЕСНЫЕ ОПЕРАЦИИ
- •3.7. ДОСТУП К ПОЛЯМ СТРУКТУР, ОБЪЕДИНЕНИЙ И ЗАПИСЕЙ
- •3.8. ДРУГИЕ ОПЕРАЦИИ
- •3.9. ПОРЯДОК ВЫПОЛНЕНИЯ ОПЕРАЦИЙ В ВЫРАЖЕНИИ
- •4. ОПЕРАТОРЫ
- •4.1. ОПЕРАТОР-ВЫРАЖЕНИЕ
- •4.2. ПУСТОЙ ОПЕРАТОР
- •4.3. СОСТАВНОЙ ОПЕРАТОР
- •4.4. УСЛОВНЫЕ ОПЕРАТОРЫ
- •4.5. ОПЕРАТОРЫ ЦИКЛА
- •while( выражение) оператор;
- •do оператор while ( выражение );
- •for( выражение1; выражение2; выражение3 ) оператор;
- •4.6. ОПЕРАТОРЫ ПЕРЕХОДА
- •break;
- •switch
- •continue;
- •goto метка;
- •5. ФУНКЦИИ. КЛАССЫ ПАМЯТИ
- •5.1. ФУНКЦИИ
- •5.2. КЛАССЫ ПАМЯТИ
- •класс памяти
- •ключевое слово
- •существование
- •видимость
- •5.3. ВОЗВРАЩЕНИЕ ЗНАЧЕНИЙ
- •5.4. АРГУМЕНТЫ ФУНКЦИИ
- •6. ФУНКЦИИ ВВОДА С КЛАВИАТУРЫ И ВЫВОДА НА ДИСПЛЕЙ
- •6.1. ФОРМАТИРОВАННЫЙ ВЫВОД
- •6.2. ФОРМАТИРОВАННЫЙ ВВОД
- •6.3. ВВОД СТРОКИ
- •6.4. ВЫВОД СТРОКИ
- •6.5. ВВОД СИМВОЛА
- •6.6. ВЫВОД СИМВОЛА
- •7. ПРЕПРОЦЕССОР
- •7.1. ВКЛЮЧЕНИЕ ФАЙЛОВ
- •7.2. ВЫПОЛНЕНИЕ ПОДСТАНОВОК
- •7.3. УСЛОВНАЯ КОМПИЛЯЦИЯ
- •8. ДИНАМИЧЕСКОЕ РАСПРЕДЕЛЕНИЕ ПАМЯТИ, СПИСКИ
- •8.1. ВЫДЕЛЕНИЕ И ОСВОБОЖДЕНИЕ ДИНАМИЧЕСКОЙ ПАМЯТИ
- •8.2. СПИСКИ
- •Рис.1. Структура однонаправленного линейного списка
- •9. ФАЙЛЫ
- •9.1. ОТКРЫТИЕ И ЗАКРЫТИЕ ФАЙЛОВ
- •9.2. ЧТЕНИЕ И ЗАПИСЬ В ФАЙЛ
- •9.3. ПРОИЗВОЛЬНЫЙ ДОСТУП К ФАЙЛУ
- •10. ЛАБОРАТОРНЫЕ РАБОТЫ
- •10.1. МАССИВЫ И СИМВОЛЬНЫЕ СТРОКИ
- •Цель работы
- •Пример выполнения работы
- •Варианты заданий
- •10.2. ФУНКЦИИ
- •Цель работы
- •Пример выполнения работы
- •Варианты заданий
- •10.3. СТРУКТУРЫ И МАССИВЫ СТРУКТУР
- •Цель работы
- •Пример выполнения работы
- •Варианты заданий
- •10.4. ДИНАМИЧЕСКОЕ РАСПРЕДЕЛЕНИЕ ПАМЯТИ, СПИСКИ
- •Цель работы
- •Пример выполнения работы
- •Варианты заданий
- •10.5. РАБОТА С ФАЙЛАМИ
- •Цель работы
- •Пример выполнения работы
- •Варианты заданий
- •11. ВВЕДЕНИЕ В C++
- •12. КЛАССЫ
- •12.1. ОБЩИЕ ПОЛОЖЕНИЯ
- •12.2. КОНСТРУКТОРЫ И ДЕСТРУКТОРЫ
- •12.3. СОЗДАНИЕ И ВЫЗОВ ОБЪЕКТОВ
- •12.4. ДРУЖЕСТВЕННЫЕ ФУНКЦИИ
- •12.5. ПЕPЕГPУЖЕННЫЕ ОПЕPАЦИИ И ФУНКЦИИ
- •12.6. ПАРАМЕТРИЗИРОВАННЫЕ КЛАССЫ
- •12.7. ПРЕОБРАЗОВАНИЕ ТИПОВ
- •12.8. СТАТИЧЕСКИЕ КОМПОНЕНТЫ КЛАССА
- •13. ПРОИЗВОДНЫЕ КЛАССЫ, НАСЛЕДОВАНИЕ
- •13.1. ИЕРАРХИЯ КЛАССОВ
- •13.2. ДОСТУП К НАСЛЕДУЕМЫМ КОМПОНЕНТАМ
- •Доступ в базовом классе
- •Модификатор доступа
- •14. ВИРТУАЛЬНЫЕ ФУНКЦИИ
- •14.1. ОБЩИЕ ПОЛОЖЕНИЯ
- •14.2. ВИРТУАЛЬНЫЕ ДЕСТРУКТОРЫ
- •14.3. АБСТРАКТНЫЕ КЛАССЫ
- •15.1. ВЫВОД ДАННЫХ
- •15.2. ВВОД ДАННЫХ
- •15.3. ВВОД-ВЫВОД ДАННЫХ, ОПРЕДЕЛЕННЫХ ПОЛЬЗОВАТЕЛЕМ
- •15.4. РАБОТА С ДИСКОВЫМИ ФАЙЛАМИ
- •15.5. ОБРАБОТКА ИСКЛЮЧЕНИЙ
- •ЛИТЕРАТУРА
– 20 –
int n;
int Probel( char *str); // Прототип функции gets(string);
puts(”Вот наша строка”);
n= Probel(string); //Вызов функции printf(”Кол-во пробелов %d”, n);
} // main
// определение функции Probel int Probel( char *str ){
int i; count=0;
for(i=0; str[i]!=’\0’; i++); if ( str[i]==’ ’) count++; return count;
} // Probel //Конец программы
(Здесь string – аргумент функции Probel, str – формальный параметр, void и int – типы возвращаемого функцией значения. Отметим, что в списке параметров прототипа достаточно было бы записать char *).
5.2. КЛАССЫ ПАМЯТИ
Класс памяти переменной определяет ее область видимости и время существования
(табл. 3).
Пример: auto int number;
Выше сплошной черты в таблице классы описываются внутри функции (внутри блока), остальные вне функций.
Таблица 3
класс памяти |
ключевое слово |
существование |
видимость |
автоматический |
аuto |
временно |
блок |
регистровый |
register |
временно |
блок |
статический |
static |
постоянно |
блок |
внешний |
extern |
постоянно |
файл, все файлы |
внешний статический |
static |
постоянно |
файл |
Класс auto (автоматическая) приписывается переменным по умолчанию. Область видимости ограничена той функцией, в которой эти переменные описаны. Эти переменные создаются в момент начала работы функции и ликвидируются в момент завершения ее работы, т.е. время существования соответствует времени выполнения функции. В частности, переменные i, count видимы только в функции Probel.
Формальные параметры функций являются локальными переменными.
Внешние (глобальные) переменные должны быть описаны до той функции, в которой используются. Внутри функции описание переменной может повторяться с дополнением ключевого слова extern. Если переменная описана вне любой функции, то областью видимости будет весь файл, если же переменная описана внутри функции, то область видимости ограничена той функцией, в которой эти переменные описаны. Внешние переменные создаются в момент начала работы всей программы и существуют до ее завершения.
Пример: int value; void main() {
extern int value;
...
}
void func() {
© 1998 Калачев Д.П., Лутай В.Н.
– 21 –
int value;
...
}
void Proof() { extern int value;
...
}
Для функций main и Proof переменная value – внешняя. В функции func переменная value – локальная, значение которой не совпадает со значением внешней переменной в
Proof и main.
Программа может быть записана в нескольких файлах. Повторение определения внешней переменной в функциях можно опустить, если все функции, в которых она используется, находятся в одном файле.
Статическая переменная, объявленная внутри функции, с точки зрения области видимости подобна автоматической, а с точки зрения времени существования – глобальной.
Пример: void main() { int i;
void print();
for( i=1; i<=3; i++) print();
}
void print() { int number=0; static int stay=0;
printf(”Номер = %d состояние = %d \n”, number++, stay++ );
}
Здесь number – локальная переменная, stay – статическая. Функция print вызывается три раза.
Номер 1 состояние 1 Номер 1 состояние 2 Номер 1 состояние 3
Внешние статические переменные, объявленные в каком-либо файле программы, доступны только в этом файле или в части файла, следующей за объявлением, в других файлах программы они невидимы.
Пример:
/*начало файла */
. . .
static char buf [10]; int myfunc() { ... }; /* Конец файла */
Переменная buf доступна только функции myfunc, но не выше; она недоступна и функциям в других файлах программы.
Для уменьшения времени выполнения программы значения переменных можно хранить не в оперативной памяти, а в регистрах процессора. Таким переменным должен быть присвоен класс register. В остальном они аналогичны автоматическим. Регистровыми можно объявлять несколько переменных, однако реально их будет столько, сколько свободных регистров у процессора.
© 1998 Калачев Д.П., Лутай В.Н.
– 22 –
5.3. ВОЗВРАЩЕНИЕ ЗНАЧЕНИЙ
При вызове функций в вызывающей программе может быть использован или не использован результат работы функции. Функция возвращает в функцию, ее вызвавшую, всегда одно значение: значение простой переменной или ее адрес или адрес составной переменной – массива, структуры. Если вызов функции является частью выражения, то в вызываемой функции должен ставиться оператор return(возвращаемое_значение); при этом тип возвращаемого значения должен совпадать с типом функции в ее заголовке. По умолчанию функция имеет целый тип. Если функция не возвращает значений (например, она осуществляет только печать данных), то она должна иметь тип void; оператор return при этом можно опустить.
В качестве примера запишем функцию, вычисляющую значения синуса с шагом 0.1, в диапазоне от 0 до 1 с точностью 0.0001.
Известное разложения в ряд имеет вид sin(x)=x-x^3/3!+x^5/5! ... Запишем этот ряд следующим образом:
A = A1-A2+A3... , где
AN+1 = -AN*x^2/(2*N*(2*N+1))
или
AN+1 = -AN*KN
(Здесь применен стандартный прием программирования для числовых рядов, состоящий в нахождении зависимости между соседними членами ряда).
void main() { double x=0, y;
double sin(double); // Прототип функции while (x<1) {
y=sin(x); // Вызов функции
printf(”x=%f sin(x)=%f\n”,x,y); //Печать значений x=x+0.1;
}
} //main
// описание функции double sin( double z) { int n=1;
double A, A1, A2;
A1=z; A=A2=A1; //А - сумма ряда,А1 - текущий член ряда, А2 - его модуль while (A2>0.0001) { // Точность проверяется по значению текущего члена ряда
A1 = -A1*z*z/(2*n*(2*n+1)) ; A = A+A1;
A2 = (A1>0)? A1:-A1; // Вычисление модуля n++;
}
return (A); } // sin
5.4.АРГУМЕНТЫ ФУНКЦИИ
ВС аргументы передаются только по значению. При вызове функции в ней создается копия аргумента. Функция работает с этой копией, не изменяя значения аргумента.
Пример: функция перестановки значений х и у. void main() {
int x, y;
void swap(int,int); // Прототип функции x=1; y=5;
swap(x,y); // Вызов функции
© 1998 Калачев Д.П., Лутай В.Н.
– 23 – printf(”x=%d, y=%d\n”); // Вывод значений
}
// Описание функции
void swap( int z1, int z2) {
int buf; // Поле для промежуточного хранения buf=z1;
z1=z2;
z2=buf;
}
Результат: х=1, у=5.
Функция не изменила значения исходных переменных. Объясняется это тем, что обмен значений она произвела в копиях переменных x и y.
Используем в качестве аргументов адреса исходных переменных. С этой целью изменим описание функции и ее вызов:
void swap( int *z1, int *z2) { int buf;
buf = *z1; *z1 = *z2; *z2 = buf;
}
swap( &x, &y );
Здесь в функцию передаются адреса переменных х и у. По-прежнему, в функции создаются копии этих адресов. Но так как *z1 и *z2 являются значениями исходных переменных, то мы получим желаемый результат.
При использовании в качестве аргумента имени массива, проблем, аналогичных предыдущим, не возникает, так как имя массива является его адресом.
void main() { int mas[10];
...
myFunct(mas); // Вызов функции
...
} // main
void myFunct(int massiv[]) {
...
} // myFunct
Если функция работает не с массивом, а с его отдельными элементами, то как и в первом случае следует прибегать к указателям.
Структуры передаются в функции также по имени.
Функция может служить в качестве аргумента функции. Передать функцию в качестве аргумента означает передать адрес первого выполняемого в этой функции оператора.
Положим, что указатель на произвольную функцию – funct. Тогда для того, чтобы обратиться к такой функции, следует написать – (*funct)(...);
В качестве примера рассмотрим программу вычисления определенного интеграла от функции sin(x) в пределах от a до b. Подынтегральную функцию назовем Sinus, функцию, вычисляющую интеграл, – Integral. В качестве метода численного интегрирования выберем простейший метод прямоугольников с разбиением интервала интегрирования на М отрезков.
#include <stdio.h>
#include <math.h> //Подключение математической библиотеки const int M=20;
double Sinus(double x){
© 1998 Калачев Д.П., Лутай В.Н.