
- •Основные понятия. Типы данных.
- •Выражения. Операторы.
- •Управляющие структуры
- •Функции. Нисходящее программирование
- •Void имя (список аргументов)
- •Рекурсия. Макросы. Условная компиляция
- •Указатели. Арифметические операции с указателями
- •Массивы указателей. Указатели на функцию. Динамические массивы
- •Динамические структуры данных
- •Режимы работы с файлами в с
Рекурсия. Макросы. Условная компиляция
Задача 1: Вычислить сумму элементов массива с помощью рекурсии.
#include <iostream>
#include <stdlib.h>
using namespace std;
int sum(int n, int a[]);
int i, n, a[100];
void main ()
{
cout<<"Vvedite n: ";
cin>>n;
cout<<"V massive "<<n<<" elementov\n";
rand();
for (i=0; i<n; i++)
{
a[i]=-10+rand(21);
cout<<a[i];
}
cout<<"Summa= "<<sum(n-1,a);
}
int sum (int n, int a[100])
{
if (n==0) return a[0]; else return a[n]+sum(n-1,a);
}
Макрос определяется директивой #define и представляет собой символическое имя некоторых операций.
Идентификатор макроса заменяется соответствующим текстом до начала компиляции.
Макрос может определяться с параметрами и без. Если макрос имеет параметры, то сначала в замещающий текст подставляются значения параметра, а затем расширенный вариант подставляется вместо идентификатора макроса.
Например:
#define Circle_area(x), (PI*(x)*(x))
…
area=Circle_area(4);
Преимущество состоит в том, что вычисления, выполняемые макросом непосредственно помещаются в текст программы и не требуют дополнительных накладных расходов, связанных с вызовом функции. Текст программы остается читаемым.
Определение макроса можно аннулировать, используя оператор #undef.
Условная компиляция позволяет программисту управлять выполнением директив препроцессора и компиляцией программного кода. Каждая условная директива препроцессора вычисляет значение целочисленного константного выражения. В качестве константного выражения в директиве использовать нельзя: операции преобразования типов, операции sizeof и константы перечисляемого типа.
#if!defined(NULL)
#define NULL 0
#endif
Эти директивы определяют не была ли определена ранее константа NULL. В случае если не определена, то определяет эту константу.
Задача 2: посчитать сумму N членов ряда Фибоначчи.
Задача 3: продемонстрировать возможности использования макросов с параметрами и без в ходе вычисления любой задачи.
Указатели. Арифметические операции с указателями
Указатель – переменная, содержащая в качестве своего значения адрес. С другой стороны указатель содержит адрес переменной, который в свою очередь хранит значение. В данном случае имя переменной отсылает к значению непосредственно, а указатель косвенно.
Ссылка на значение по форме указателя называется косвенной адресацией.
Тип *имя;
Указатель должен инициализироваться либо при своем определении, либо перед началом использования с помощью оператора присваивания. В качестве начальных значений указатель может принимать (0, NULL, адрес).
Операторы для работы с указателями:
Разыменование: *. Является унарной операцией и возвращает значение, которое хранится по указанному адресу.
Оператор получения адреса: &. Является унарной операцией и возвращает адрес своего операнда. Например: m=&count (записывает в переменную m адрес переменной count).
В С++ нельзя изменить тип указателя, не используя явное приведение типа.
Арифметические действия с указателями:
-
С указателями можно выполнять операции сравнения и присваивания.
-
Указатель можно увеличивать и уменьшать.
-
Указателями можно складывать и вычитать из указателя целые числа.
-
Указатели можно вычитать один из другого.
-
Указатель можно присвоить один другому.
Умножение и деление указателей ЗАПРЕЩЕНО!
Указатель можно присвоить другому если они оба имеют одинаковый тип. Исключением из этого правила является указатель *void. Данному можно присвоить любой другой, но сам указатель на void другого типа присвоить нельзя. Указатель на void не может быть разыменован.
Например:
int v[10];
int *vPtr;
vPtr=v или vPtr=&v[0];
vPtr+=2;
Задание 1: Найти сумму элементов массива, расположенных между вторым и предпоследним отрицательными элемента массива.
#include <iostream>
using namespace std;
int main()
{
int a[100],s, n, c=0, x,y;
cout<<"Vvedite N: ";
cin >>n;
for (int i=0;i<n;i++)
{
cout<<"a["<<i<<"]= ";
cin>>a[i];
}
for (int i=0; i<n; i++)
{
if(a[i]<0)
{
c++;
if (c==2) x=i;
}
}
c=0;
cout<<x<<endl;
for (int i=(n-1); i>=0; i--)
{
if(a[i]<0)
{
c++;
if (c==2) y=i;
}
}
cout<<y<<endl;
s=0;
for (int i=x; i<=y;i++)
{
s+=a[i];
}
cout<<s<<endl;
system("pause");
return 0;
}
Задание 2: Посчитать количество элементов, расположенных левее последнего отрицательного.
#include <iostream>
using namespace std;
int main()
{
int a[100],s=0, n, c=0, x,y;
cout<<"Vvedite N: ";
cin>>n;
for (int i=0;i<n;i++)
{
cout<<"a["<<i<<"] = ";
cin>>a[i];
}
for (int i=(n-1);i>=0;i--)
{
if (a[i]<0)
{
x=i;
break;
}
}
s=x++;
cout<<s<<endl;
system("pause");
return 0;
}
Задание 3: реализовать рекурсию функции ∑2N 1/(n-1)!
#include <iostream>
using namespace std;
double fact(int);
int main()
{
int n;
double s=0;
cout<<"Vvedite N= ";
cin>>n;
for (int i=2; i<=n;i++)
{
s+=1/fact(i-1);
}
cout<<s<<endl;
system("pause");
return 0;
}
double fact (int x)
{
if (x==0) return 1;
else return x*fact(x-1);
}