Компоновка нескольких файлов в одну программу
С помощью компилятора текст преобразуется в исполняемый файл. Обработка исходных файлов происходит в три этапа. Сначала файл обрабатывается препроцессором, который выполняет операторы #include, #define и еще несколько других.
Затем, на втором этапе, компилятор создает объектный файл, в котором имеются ссылки на различные системные функции и на стандартные функции языка C++.
На третьем этапе компиляции к объектному файлу подсоединяются все функции на которые он ссылается.
Основная цель многоэтапной компиляции программ – возможность компоновать программу из многих файлов. Каждый файл представляет собой законченный фрагмент программы, который может ссылаться на функции, переменные или классы, определенные в других файлах.
Исполняемая программа представляет собой непрерывный блок, который состоит из четырех частей:
--Програмный код
--Глобальные переменные
--Куча (Heap) , где хранятся динамические переменные
--Стек (stack).
В стеке хранятся:
-Адреса возврата из функций
-Значения аргументов функций
-Локальные переменные
В языке Си существует строгое правило, в соответствии с которым все переменные и функции должны быть объявлены или определены.
В программе должно быть только одно определение функции. Удобно было бы поместить Определение функции в отдельный файл, а в других файлах в начале помещать лишь объявление, прототип функции.
Пример использования указателей на функции
Последовательность действий следующая:
Создать файл point_function.cpp
Создать файл function.cpp
Создать файл function.h
Директивы препроцессора
Назначение препроцессора - обработка исходного текста программы до ее компиляции.
Препроцессор обрабатывает собственные директивы. Эти директивы задаются, как правило, в отдельной строке и начинаются с символа ’#’.
В языке C++ можно задать следующие директивы препроцессора:
· директивы компилятора #pragma, указывающие компилятору, как именно необходимо строить объектный код;
· директива включения файла #include, с помощью которой можно включить в текст программы текст из другого файла;
· директивы условной компиляции
#if, #else, #elif, #endif, #ifdef, #ifndef, defined;
· директива определения лексем #define;
· директива отмены определения #undef
Директива #include может быть записана в одном из двух форматов:
#include<имяфайла> и #include”имяфайла”
Первый формат позволяет включить имя файла из тех папок, которые заданы как стандартные для хранения включаемых файлов.Второй формат дает возможность записать произвольное имя файла.
Директива #defineпозволяет определить новые лексемы. Ее формат:
#defineимялексемы [ (параметры) ] текстлексемы
Лексемы с параметрами называют макроопределениями( макросами). Такие конструкции позволяют выполнить замещение лексем по-разному, в зависимости от фактических параметров.
Рекурсии
При решении многих задач пользуются методом сведения данной задачи к задаче, с меньшим числом предметов. Такой метод называют методом рекуррентных соотношений.
Существует класс задач, которые обладают таким свойством: вычисляя последующие значения интересующей нас величины, мы пользуемся только фиксированным числом последних значений.
Последовательности с таким свойством называют рекуррентными
Рекурсивным называется объект, который частично определяется через самого себя.
Максимальное число рекурсивных вызовов процедуры без возвратов, которое происходит во время выполнения программы, называется глубиной рекурсии.
Число рекурсивных вызовов в каждый конкретный момент времени, называетсятекущим уровнем рекурсии.
В общем случае любая рекурсивная процедура включает в себя некоторое множество операторов S и один или несколько операторов рекурсивного вызова.
Безусловныерекурсивные процедура приводят к бесконечным процессам, так как практическое использо-вание процедур с бесконечным самовызовом невозможно.
Такая невозможность вытекает из того, что для каждой копии рекурсивной процедуры необходимо выделял дополнительную область памяти, а бесконечной памяти не существует.
Следовательно, главное требование к рекурсивным процедурам заключается в том, что вызов рекурсивной процедуры должен выполняться по условию, которое на каком-то уровне рекурсии станет ложным.
Если условие истинно, то рекурсивный спуск продолжается. Когда оно станет ложным, спуск заканчивается и начинается поочередный рекурсивный возврат из всех вызванных на данный момент копий рекурсивной процедуры.
Формы рекурсивных процедур.
Структура рекурсивной процедуры может принимать три разные формы:
1. Форма с выполнением действий до рекурсивного вызова
(с выполнениеем действий на рекурсивном спуске).
void Rec();
{S; if (условие) Rec();};
2.Форма с выполнением действий после рекурсивного вызова
(с выполнением действий на рекурсивном возврате).
void Rec();
{if (условие) Rec(); S;};
3. Форма с выполнением действий как до, так и после рекурсивного вызова (с выполнением действий как на рекурсивном спуске, так и на рекурсивном возврате).
void Rec();
{ S1;
if (условие) Rec();
S2;}
Динамическое программирование (ДП) — это вычислительный метод для эффективного решения задач с пересекающимися подзадачами. Возникло и сформировалось в 1950-53г. благодаря работам Р.Беллмана.
Идея динамического программирования состоит в разбиении задачи на несколько независимых подзадач, решении каждой из них, а затем вычислении результата.
Для решения подзадач этот же алгоритм применяется рекурсивно или итерационно. При этом для каждой подзадачи запоми-нается вычисленный ответ, и если на каком-то шаге встретилась подзадача второй раз, то вычисления для нее не производятся.
За счет большого количества пересекающихся подзадач это значительно уменьшает время работы.
В математике существуют числа Фибоначчи. Это числа следующего вида:1; 1 ; 2; 3; 5;……………
Таким образом каждое следующее число получается как сумма двух предыдущих.Рекурсивное определение для чисел Фибоначчи :
Рекурсивная функция вычисления чисел Фибоначчи
int FibR(int n)
{
if ((n == 1) || (n == 2))
return 1;
else
return FibR(n - 1) + FibR(n - 2);
}
Рекурсивный НОД
int f_nod( int x,y)
{ рекурсивная функция}
{
if (y>x) return f_nod(y,x);
else if (y<=0) return x;
else return f_nod(y,x mod y);
};
Двоичный поиск элемента в упорядоченной последовательности }
void Search_bin(int *a, int l, int r,int x)
int k,p,i,j;
{ k= (l+r) / 2;
if (a[k]==x) return k;
else
{ if (a[k] <=x)
l=k+1;
else r=k-1;
return Search_bin (a,l,r,x); }}
{поиск наибольшего элемента элемента в последовательности }
int mmax (int *a, int i,int n)
{
if (i==n) mmax=a[i];
else
if ( (a[i]> mmax(a,i+1) && (i==n))
mmax=a[i];
else mmax= mmax(a,i+1,n);
}
Это задача поиска наибольшей общей последовательности, ( Longest Common Subsequence, LCS)которая является подпоследовательностью нескольких последовательностей (обычно двух).
Рекурсивное решение:
int lcs_length(char * A, char * B)
{
if (*A == '\0' || *B == '\0') return 0;
else if (*A == *B)
return 1 + lcs_length(A+1, B+1);
else
return
max(lcs_length(A+1,B), lcs_length(A,B+1));
}
Итерационное решение наибольшей подпоследовательности
char* getLongComSub(char *a, char *b)
{
char **max_len,*res;
max_len= (char **) malloc(strlen (a) + 1);
res= (char *) malloc(strlen (b) + 1);
for(int i = 0; i <= strlen (a); i++)
max_len[i]= (char *) malloc(strlen (b) + 1);
for( i = strlen (a)- 1; i >= 0; i--)
{
for(int j = strlen (b) - 1; j >= 0; j--)
{ if(a[i] == b[j])
{
max_len[i][j] = 1 + max_len[i+1][j+1];
}
else
{max_len[i][j] = max(max_len[i+1][j], max_len[i][j+1]);
}
}
}
k++;
i++;
j++;
//продолжение наибольшей подпоследовательности
int j,k=0;
for( i = 0, j = 0; max_len[i][j] != 0; )
{
if(a[i] == b[j])
{
res[k]=a[i];
res[k+1]='\0';
k++; i++; j++;
}
else
{ if(max_len[i][j] == max_len[i+1][j])
i++;
else j++; } }
return res;
}
//Палиндром
#include <stdlib.h>
#include <string.h>
void insert(int c,char *A,int n)
{
int i=0;
int len=strlen(A);
int t=len;
while(t>=n)
{
A[1+t]=A[t];
--t;
}
A[n]=c;
}
void pal(char *st, int l,int r)
{
int t,i;char ch;
if (l>=r)
return;
else
if (st[l]==st[r])
pal(st,l+1,r-1);
else
// продолжение от палиндрома
if (st[l]==st[r-1])
{
ch=st[r];
insert(ch,st,l);
proc(st,l+2,r-1);
}
else
{
ch=st[l];
insert(ch,st,r+1);
proc(st,l+1,r);
} }
void main ()
{
char x[100]="12345";
proc(x, 0,5);
puts (x);
}