Презентацию к лекции Вы можете скачать здесь.
В
Следованием называется конструкция, представляющая собой последовательное выполнение двух или более операторов (простых или составных).
Ветвление задает выполнение либо одного, либо другого оператора в зависимости от выполнения какого-либо условия.
Цикл задает многократное выполнение оператора.
Особенностью базовых конструкций является то, что любая из них имеет только один вход и один выход (см. рис. 3.1), поэтому конструкции могут вкладываться друг в друга произвольным образом.
(рис 3.1) Базовые конструкции структурного программированияЦелью использования базовых конструкций является получение программы простой структуры. Такую программу легко читать, отлаживать и при необходимости вносить в нее изменения.
Любое выражение, завершающееся точкой с запятой, рассматривается как оператор, выполнение которого заключается в вычислении выражения. Частным случаем выражения является пустой оператор ; (он используется, когда по синтаксису оператор требуется, а по смыслу - нет). Примеры:
i++; //выполняется операция инкремента a *= b + c; //выполняется умножение с присваиванием
Условный оператор if используется для разветвления процесса вычислений на два направления.
if ( выражение ) оператор_1; [else оператор_2;]
Сначала вычисляется выражение, которое может иметь арифметический тип или тип указателя. Если оно не равно нулю, выполняется первый оператор, иначе - второй. После этого управление передается на оператор, следующий за условным. Одна из ветвей может отсутствовать.
Если в какой-либо ветви требуется выполнить несколько операторов, их необходимо заключить в блок. Блок может содержать любые операторы, в том числе описания и другие условные операторы.
Примеры:
if (a<0) b = 1; // 1
if (a<b (a>d || a==0)) b++;
else {b *= a; a = 0;} // 2
if (a<b) {if (a<c) m = a; else m = c;}
else {if (b<c) m = b; else m = c;} // 3
В примере 1 отсутствует ветвь else. Подобная конструкция называется "пропуск оператора", поскольку
Если требуется проверить несколько условий, их объединяют знаками
Оператор в примере 3 вычисляет наименьшее значение из трех переменных.
(рис 3.2) МишеньПример. Производится выстрел по мишени, изображенной на рис. 3.2. Определить количество очков.
#include <iostream>
using namespace std;
int main()
{float x, y; int kol;
cout << "Введите координаты выстрела\n";
cin >> x >> y;
if ( x*x + y*y < 1 ) kol = 2;
else if ( x*x + y*y < 4 ) kol = 1;
else kol = 0;
cout << "\n Очков: " << kol;
}
Оператор switch (переключатель) предназначен для разветвления процесса вычислений на несколько направлений. Формат оператора:
switch ( выражение ){
case константное_выражение_1: операторы_1;
case константное_выражение_2: операторы 2;
...
case константное_выражение_n: операторы n;
[default: операторы ;]}
Выполнение оператора начинается с
Все константные выражения должны иметь разные значения, но быть одного и того же default (а при его отсутствии управление передается следующему за оператору).
Пример (программа реализует простейший калькулятор на 4 действия):
#include <iostream>
using namespace std;
int main()
{
int a, b, res; char op;
cout << "\nВведите 1й операнд : ";
cin >> a;
cout << "\nВведите знак операции : ";
cin >> op;
cout << "\nВведите 2й операнд : ";
cin >> b;
bool f = true;
switch (op)
{
case '+': res = a + b; break;
case '-': res = a - b; break;
case '*': res = a * b; break;
case '/': res = a / b; break;
default : cout <<"\nНеизвестная операция";
f = false;
}
if (f) cout << "\nРезультат : " << res;}
Выход из или return.
Любой цикл состоит из тела цикла, то есть тех операторов, которые выполняются несколько раз, начальных установок, блока модификации параметра цикла и проверки условия выхода из цикла (рис. 3.3),
которая может размещаться либо до
(рис 3.3) Два вида цикловОдин проход цикла называется итерацией. Переменные, принудительно изменяющиеся в цикле и использующиеся при проверке условия выхода из него, называются параметрами цикла. Целочисленные параметры цикла, изменяющиеся на целое число на каждой
Нельзя передавать управление извне внутрь цикла. Выход из цикла возможен как при выполнении условия выхода, так и по операторам , return или
Цикл с предусловием реализует
while ( выражение ) оператор;
Выражение определяет условие повторения
Пример (программа печатает таблицу y=x2+1 во введенном диапазоне):
#include <cstdio>
using namespace std;
int main()
{
float Xn, Xk, Dx;
printf("Введите диапазон и шаг изменения аргумента: ");
scanf("%f%f%f", Xn, Xk, Dx);
printf("| X | Y |\n"); //шапка таблицы
int X = Xn; //начальные установки цикла
while (X<=Xk)
{ //проверка условия выхода
printf("| %5.2f | %5.2f |\n", X, X*X + 1); //тело
X += Dx; //модификация
}
}
Цикл с постусловием реализует
do оператор while выражение;
Сначала выполняется простой или
Пример (программа осуществляет проверку ввода):
#include <iostream>
using namespace std;
int main(){
char answer;
do{
cout << "\nКупи слоника! ";
cin >> answer;
}while (answer != 'y');}
Цикл с параметром имеет следующий формат:
for ( инициализация; выражение; модификации) оператор;
Пример:
for ( int i = 1; i < 6; ++i ) printf( " %d ", i ); printf( "вышел зайчик погулять" );
Инициализация используется для объявления и присвоения начальных значений величинам, используемым в цикле. В этой части можно записать несколько операторов, разделенных запятой.
Выражение определяет условие выполнения цикла: если оно не равно 0 (истинно), цикл выполняется.
Модификации выполняются после каждой
Простой или составной оператор представляет собой тело цикла. Любая из частей оператора for может быть опущена (но точки с запятой надо оставить на своих местах!). В любой части можно использовать операцию "запятая" (последовательное вычисление), например:
for (int i = 1, s = 0; i<=100; i++) s += i; // сумма чисел от 1 до 100
Пример (программа печатает таблицу
#include <cstdio>
using namespace std;
int main()
{
float Xn, Xk, Dx;
printf("Введите диапазон и шаг изменения аргумента: ");
scanf("%f%f%f", Xn, Xk, Dx);
printf("| X | Y |\n");
for (int X = Xn; X<=Xk; X += Dx)
printf("| %5.2f | %5.2f |\n", X, X*X + 1);
}
В С++ есть пять операторов, изменяющих естественный порядок выполнения вычислений:
break ;continue ;return ;goto ;throw .Оператор выхода используется для немедленного завершения . Выполнение передается следующему после завершенного оператору.
Оператор перехода к следующей итерации цикла пропускает все операторы, оставшиеся до конца for ) и начало следующей
Оператор возврата из функции return завершает выполнение функции и передает управление в точку ее вызова. Мы рассмотрим его вместе с функциями на следующей лекции.
Оператор безусловного перехода имеет формат:
goto метка;
В теле той же функции должна присутствовать ровно одна конструкция вида:
метка: оператор;
Оператор передает управление на помеченный оператор. Метка - это обычный идентификатор,
Использование
В остальных случаях для записи любого алгоритма существуют более подходящие средства.
Исключительную ситуацию (или просто исключение ) генерирует либо программист с помощью оператора , либо сама среда выполнения. Это происходит, когда во время выполнения программы возникают какие-либо ошибки, например, деление на ноль или С++, позволяет реагировать на подобные ошибки и таким образом избегать аварийного завершения программы.
Пример использования оператора . Программа вычисляет значение синуса вещественного аргумента х с заданной точностью с помощью разложения в бесконечный ряд:
sh x = x - x3/3! + x5/5! - x7/7! + …
Точность достигается при |Rn| < , где Rn —остаточный член ряда, который для данного ряда можно заменить величиной очередного члена ряда, прибавляемого к сумме.
#include <cmath>
#include <iostream>
using namespace std;
int main()
{
const int MaxIter = 500; //ограничитель количества итераций
double x, eps;
cout << "\nВведите аргумент и точность: ";
cin >> x >> eps;
bool done = true; //признак успешного вычисления
double y = x, ch = x; // сумма и первый член ряда
for (int n = 0; fabs(ch) > eps; n++)
{
ch *= -x * x /(2 * n + 2)/(2 * n + 3); //очередной член ряда
y += ch;
if (n > MaxIter)
{
cout << "\nРяд расходится!";
done = false; break;
}
}
if (done)
cout << "\nЗначение функции: " << y;}
Указатели предназначены для хранения адресов областей памяти. Указатель не является самостоятельным типом данных, он всегда связан с каким-либо другим конкретным типом. В С++ есть три вида указателей, отличающихся свойствами и набором допустимых операций:
Наиболее часто используются типизированные указатели, то есть указатели, которые ссылаются на величины определенного типа. С ними разрешается выполнять арифметические действия. С бестиповым указателем никаких
Указатель на функцию - это особый вид указателя, который применяется для косвенного вызова функции. С ним также нельзя выполнять никаких арифметических действий. Указатель функции содержит адрес в
тип (*имя) ( список_типов_аргументов );
Например, объявление:
int (*fun) (double, double);
задает указатель с именем fun на функцию, возвращающую значение типа и имеющую два аргумента типа .
Типизированный указатель содержит адрес области памяти, в которой хранятся данные определенного типа. Простейшее объявление указателя данных имеет вид:
тип *имя;
где тип может быть любым, кроме ссылки и
Звездочка относится непосредственно к имени, поэтому для того, чтобы объявить несколько указателей, требуется ставить ее перед именем каждого. Например, в операторе
int *a, b, *c;
описываются два указателя на целое с именами a и c, а также целая переменная b.
Размер указателя зависит от модели памяти. Можно определить указатель на указатель, например, ;. Значением такой переменной должен быть адрес указателя - получается двойное косвенное обращение. Количество звездочек (уровней косвенности) стандартом не ограничено.
Можно описать указатель на тип void и присвоить ему значение указателя любого типа, а также сравнивать его с любыми указателями, но перед выполнением каких-либо действий с областью памяти, на которую он ссылается, требуется явным образом преобразовать его к конкретному типу.
Указатель может быть
int i; // целая переменная const int ci = 1; // целая константа int * p0 = i; // 1 - указатель на переменную // int * p1 = ci; // 2 - ошибка трансляции! int * p2 = const_cast<int*>( ci ); // 2.1 const int * pc0 = ci; // 3 - указатель на константу int const * pc2 = ci; // 3.1 - тоже указатель на константу const int * pc1 = i; // 4 int const * pc3 = i; // 4.1 int * const cp0 = i; // 5 - указатель-константа на переменную // int * const cp1 = ci; // 6 - ошибка трансляции! const int * const cpc0 = ci; // 7 - указатель-константа на константу const int * const cpc1 = i; // 8
Величины типа указатель подчиняются общим правилам определения
Указатели чаще всего используют при работе с динамической памятью. Доступ к выделенным участкам динамической памяти, называемым динамическими переменными, производится только через указатели.
Время жизни
В С ++ используется два способа работы с динамической памятью. Первый использует семейство функций malloc и достался в наследство от С, второй использует операции new и delete.
Существуют следующие способы инициализации указателя:
int a = 5; // целая переменная int* p = a; // в указатель записывается адрес a int* p (a); // то же самое другим способом
int* r = p;
int b[10]; // массив
int* t = b; // присваивание имени массива
...
void f(int a ){ /* … */ } // определение функции
void (*pf)(int); // указатель на функцию
pf = f; // присваивание имени функции
char* vp = (char *)0xB8000000; // шестнадцатеричная константа
int* suxx = NULL; // не рекомендуется int* rulez = 0; // так - лучше
new:int* n = new int; // 1 int* m = new int (10); // 2 int* q = new int [10]; // 3
malloc:int* u = (int*)malloc(sizeof(int)); // 4
Освобождение памяти, выделенной с помощью операции new, должно выполняться с помощью delete, а памяти, выделенной функцией malloc - посредством функции . При этом переменная-указатель сохраняется и может инициализироваться повторно. Приведенные выше
delete n; delete m; delete [] q; free (u);
ВНИМАНИЕ
Если переменная-указатель выходит из области своего действия, отведенная под нее память освобождается. При этом память из-под самой динамической переменной не освобождается.
С указателями можно выполнять следующие операции: разадресация (*),
Операция разадресации, или разыменования, предназначена для доступа к величине, адрес которой хранится в указателе. Эту операцию можно использовать как для получения, так и для изменения значения величины (если она не объявлена как
char a; // переменная типа char char * p = new char;/* выделение памяти под указатель */ /* и под динамическую переменную типа char */ // присваивание значения обеим переменным *p = 'Ю'; a = *p;
На одну и ту же область памяти может ссылаться несколько указателей различного типа. Примененная к ним операция разадресации даст разные результаты.
Синтаксис операции явного приведения типа прост: перед именем переменной в скобках указывается тип, к которому ее требуется преобразовать, например:
unsigned long int A=0Xсс77ffaa; unsigned int* pint =(unsigned int *) A;
Эта операция унаследована из С и считается устаревшей, поскольку не обеспечивает безопасности. Явное С++ и reinterpret_cast, например:
void *pointer = static_cast<void *>( a ); pointer = reinterpret_cast<void *>( pa );
Преобразование reinterpret_cast. Операция не выполняет преобразование
При смешивании в выражении указателей разных типов явное . Указатель может неявно преобразовываться в значение типа bool.
Присваивание без явного приведения типов допускается только указателям типа или если тип указателей справа и слева от
Арифметические операции с указателями (
Инкремент перемещает указатель к следующему элементу массива, декремент - к предыдущему.
Фактически значение указателя изменяется на величину sizeof(тип).
При записи выражений с указателями следует обращать внимание на
*p++ = 10;
То же самое можно записать подробнее:
*p = 10; p++;
Выражение (*p)++, напротив, инкрементирует значение, на которое ссылается указатель.
Унарная операция получения адреса применима к величинам, имеющим имя и размещенным в оперативной памяти. Нельзя получить адрес
Ссылка является альтернативным именем объекта или функции. Иными словами, ссылка - это
Ссылки в основном используются при
тип имя;
где тип - это тип величины, на которую указывает ссылка, - оператор ссылки, означающий, что следующее за ним имя является именем переменной
int kol; int pal = kol; //ссылка pal - альтернативное имя для kol const char CR = '\n'; //ссылка на константу
Разрешается объявлять константную ссылку, то есть ссылку на
const char CR = '\n'; // ссылка на константу
extern или ссылается на поле данных класса.Ссылки позволяют использовать в функциях переменные, передаваемые по адресу, без операции разадресации, что улучшает читабельность программы.
При использовании простых переменных каждой области памяти для
Конечная именованная последовательность однотипных величин называется массивом.
В С++ различают массивы фиксированного размера и массивы переменного размера ( динамические ). Количество элементов в массиве первого типа известно при написании программы и никогда не меняется. Память под такой массив выделяет компилятор.
Количество элементов динамического массива на этапе
Описание массива фиксированного размера отличается от описания простой переменной наличием после имени квадратных скобок, в которых задается количество элементов массива ( размерность ):
float a [10]; //Пример описания массива из 10 вещественных чисел
Тип элементов массива - любой допустимый тип С++, например, встроенный или библиотечный, кроме типа . Элементы массива нумеруются с нуля. Глобальный массив по умолчанию инициализируется нулями. Локальный массив, как и обычная переменная, по умолчанию никак не инициализируется. Инициализирующие значения при желании задают в
int b[5] = {3, 2, 1}; // b[0]=3, b[1]=2, b[2]=1, b[3]=0, b[4]=0
Для доступа к элементу массива после его имени указывается номер элемента ( индекс ) в квадратных скобках. В следующем примере подсчитывается
#include <iostream>
using namespace std;
int main(){
const int n = 10;
int marks[n] = {3, 4, 5, 4, 4};
for (int i = 0, sum = 0; i<n; i++) sum += marks[i];
cout << "Сумма элементов: " << sum;}
Динамические массивы создают с помощью операции new, при этом необходимо указать тип и
float *p = new float [100];
В этой строке создается переменная-указатель на , в динамической памяти отводится непрерывная область, достаточная для размещения 100 элементов вещественного типа, и адрес ее начала записывается в указатель p.
Преимущество
Память, зарезервированная под new [], должна освобождаться оператором delete [], а память, выделенная функцией malloc - посредством функции , например:
delete [] p; free (q);
Многомерные массивы фиксированного размера задаются указанием каждого измерения в квадратных скобках, например, оператор
задает описание двумерного массива из 6 строк и 8 столбцов. В памяти такой массив располагается в последовательных ячейках построчно. Многомерные массивы размещаются так, что при переходе к следующему элементу быстрее всего изменяется последний индекс.
Для доступа к элементу многомерного массива указываются все его индексы, например, matr[i][j].
Инициализация многомерного массива:
int mass2 [][] = { {1, 1}, {0, 2}, {1, 0} };
int mass2 [3][2] = {1, 1, 0, 2, 1, 0};
Для создания многомерного массива в динамической памяти необходимо указать все его
matr = new int [a] [b];
Освобождение памяти из-под массива с любым количеством измерений выполняется с помощью операции delete []. Указатель на
Пример. Программа определяет в целочисленной
#include <сstdio>
#include <iomanip>
using namespace std;
int main()
{
const int nstr = 4, nstb = 5; // размерности массива
int b[nstr][nstb]; // описание массива
int i, j;
for ( i = 0; i < nstr; i++ ) // ввод массива
for ( j = 0; j < nstb; j++ )
scanf( "%d", b[i][j] );
int istr = -1, MaxKol = 0;
for ( i = 0; i < nstr; i++ ) // просмотр массива по строкам
{
int Kol = 0;
for ( j = 0; j < nstb; j++ )
if (b[i][j] == 0) Kol++;
if ( Kol > MaxKol )
{ istr = i; MaxKol = Kol; }
} printf( " Исходный массив:\n" );
for ( i = 0; i < nstr; i++ )
{
for ( j = 0; j < nstb; j++ )
printf( "%d ", b[i][j] );
printf( "\n" );
}
if ( istr == -1 ) printf( "Нулевых элементов нет" );
else printf( "Номер строки: %d", istr );
}
Создание и обработка динамических многомерных массивов иллюстрируется примером
#include <iostream>
using namespace std;
int main()
{
int i, j, n;
cout << "Введите размеры матриц А, B, R ";
cin >> n;
// выделение памяти под матрицы
float **a = new float*[n]; // указатель на матрицу А
for( j = 0; j < n; j++ )
a[j] = new float [n];
float **b = new float*[n]; // указатель на матрицу В
for( j = 0; j < n; j++ )
b[j] = new float [n];
float **r = new float*[n]; // указатель на матрицу R
for( j = 0; j < n; j++ )
r[j] = new float [n];
// ввод матриц А и В
for ( i = 0; i < n; i++ )
{
for ( j = 0; j < n; j++ )
cin >> a[i][j];
cout << endl;
}
cout << endl;
for ( i = 0; i < n; i++ )
{
for ( j = 0; j < n; j++ )
cin >> b[i][j];
cout << endl;
}
cout << endl;
for ( i = 0; i < n; i++ ) // умножение матриц
for ( j = 0; j < n; j++ )
{
float s = 0;
for ( int k = 0; k < n; k++ )
s += a[i][k] * b[k][j];
r[i][j] = s;
}
cout << "Ответ" << endl; // вывод на экран матрицы-результата
for ( i = 0; i < n; i++ )
{
for ( j = 0; j < n; j++ )
cout <<setw(6) << r[i][j];
cout << endl;
}
// уничтожение динамических массивов
for ( i = 0; i < n; i++ ) delete[] a[i]; delete[]a;
for ( i = 0; i < n; i++ ) delete[] b[i]; delete[]b;
for ( i = 0; i < n; i++ ) delete[] r[i]; delete[]r;
}
После выполнения вычислений память освобождается. Сначала освобождают массивы для хранения элементов
Строка представляет собой
char str[10] = "Vasia";
В этом примере под строку выделяется 10
char str[] = "Vasia"; //Выделено и заполнено 6 байт
Оператор
char *str = "Vasia"
создает не
Для работы со строками С нужно подключить к программе
Пример (программа запрашивает пароль не более трех раз):
#include <cstdio> // библиотека ввода-вывода
#include <cstring> // библиотека для работы со строками старого стиля
#include <clocale> // библиотека локализации
using namespace std;
int main()
{
setlocale( LC_ALL, "rus" );
char s[5],
passw[] = "kuku"; // passw - эталонный пароль
bool ok = false;
for ( int i = 0; ! ok i < 3; ++i )
{
printf( "\nвведите пароль (4 символа):\n" );
gets( s ); // ввод строки c клавиатуры
if ( strcmp( s, passw ) == 0 )
ok = true; // сравнение строк
}
if ( ok )
printf( "\nпароль принят\n" );
else printf( "\nпароль не принят\n" );
}
ПРИМЕЧАНИЕ
Библиотечные функции работы со строками С объявлены в стандарте устаревшими, так как они не обеспечивают необходимой безопасности. Например, если в приведенную выше программу ввести строку, превышающую 4 символа, программа может завершиться аварийно.
При работе со строками часто используются указатели. Для примера рассмотрим копирование строки src в строку dest:
#include <iostream>
using namespace std;
int main()
{ char src[10];
cin >> src; // ввод строки до первого пробела
char *dest = new char [10],
*d = dest, *s = src;
while ( *d++ = *s++ ); // копирование строки
cout << dest;
}
При написании программ часто возникает потребность определить несколько
enum [ имя_типа ] { список_констант };
Имя типа задается в том случае, если в программе требуется определять переменные этого типа. Компилятор обеспечивает, чтобы эти переменные принимали значения только из списка
enum Err { ERR_READ, ERR_WRITE, ERR_CONVERT};
Err error;
...
switch (error)
{ case ERR_READ: /* операторы */ break;
case ERR_WRITE: /* операторы */ break;
case ERR_CONVERT: /* операторы */ break;}
Константам ERR_READ, ERR_WRITE, ERR_CONVERT присваиваются значения 0, 1 и 2 соответственно.
В отличие от массива, все элементы которого однотипны, структура может содержать элементы разных типов. В языке С++ структура является видом класса и обладает всеми его свойствами, но во многих случаях достаточно использовать структуры так, как они определены в языке С:
struct [ имя_типа ] {тип_1 элемент_1;тип_2 элемент_2;*тип_n элемент_n;}
[ список_описателей ];
Элементы структуры называются полями структуры и могут иметь любой тип, кроме типа этой же структуры, но могут быть указателями на него.
Если отсутствует имя типа, должен быть указан список
struct
{
char fio[30];
int date, code;
float salary;
}stuff[100], *ps; /*определение массива структур и указателя на структуру */
Если список отсутствует, описание структуры определяет новый тип, имя которого можно использовать в дальнейшем наряду со стандартными типами, например:
struct Worker
{ //описание нового типа Worker
char fio[30];
int date, code;
float salary;
}; //описание заканчивается точкой с запятой
Worker stuff[100], *ps; /* определение массива типа Worker */
/* и указателя на тип Worker */
Для инициализации структуры значения ее элементов перечисляют в
Struct
{
char fio[30];
int date, code;
float salary;
}worker = {"Страусенко", 31, 215, 3400.55};
Для переменных одного и того же
Структуру можно передавать в функцию и возвращать в качестве
Доступ к полям структуры выполняется с помощью операций выбора . (точка) при обращении к полю через имя структуры и -> при обращении через указатель, например:
Worker worker, stuff[100], *ps; ... worker.fio = "Страусенко"; stuff[8].code = 215; ps->salary = 0.12;
struct Options {
bool centerX:1;
bool centerY:1;
unsigned int shadow:2;
unsigned int palette:4;};
Доступ к полю осуществляется по имени. Адрес поля получить нельзя.
Объединение ( union ) представляет собой частный случай структуры, все поля которой располагаются по одному и тому же адресу. Формат описания такой же, как у структуры, только вместо ключевого слова struct используется слово union.
Длина объединения равна наибольшей из длин его полей. В каждый момент времени в переменной типа объединение хранится только одно значение, и ответственность за его правильное использование лежит на программисте.
Объединения применяют для экономии памяти, а также для разной интерпретации одного и того же битового представления:
struct Options {
bool centerX:1;
bool centerY:1;
unsigned int shadow:2;
unsigned int palette:4;
};
union {
unsigned char ch;
Options bit;
}option={0xC4};
cout << option.bit.palette;
option.ch = 0xF0; // наложение маски
По сравнению со структурами на объединения налагаются некоторые ограничения:
Для того чтобы сделать программу более ясной, можно задать типу новое имя с помощью ключевого слова typedef:
typedef тип новое_имя [ размерность ];
typedef unsigned int UINT;
typedef char Msg[100];
typedef struct{
char fio[30];
int date, code;
float salary;} Worker;
Введенное таким образом имя можно использовать таким же образом, как и имена стандартных типов:
UINT i, j; //две переменных типа unsigned int Msg str[10]; //массив из 10 строк по 100 символов Worker stuff[100]; //массив из 100 структур
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.