Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
МП 1,2.doc
Скачиваний:
11
Добавлен:
05.11.2018
Размер:
2.77 Mб
Скачать

3.2. Подпрограмма активизации меню

Все подпрограммы, участвующие в организации иерархического меню, имеют один параметр – номер фрейма. Меню считается активным, если его опции были выведены на экран, и не была вызвана подпрограмма восстановления области вывода меню. Активизация меню полностью повторяет действия подпрограммы создания исчезающего меню за исключением шага восстановления. Она выполняет последовательность действий:

  • сохраняет область вывода меню;

  • выводит меню и рамку;

  • получает от пользователя номер выбранной опции;

  • возвращает номер выбранной опции.

Ее аргументом, как и у вызываемых ею функций draw_border(), display_num(), save_video(), get_resp(), служит номер фрейма. Ниже приведём текст подпрограммы активации меню.

int pulldown(int num)

{

int choice;

void_mem=(char far*)0xB8000000;

//установка внешнего указателя на видеопамять

if (!frame[num].active) //если не активно

{

save_video(num);

frame[num].active=1; //признак активности

}

if (frame[num].border) draw_ border(num);

display_menu(num); //вывод меню

return get_resp(num); } //возврат выбора

Вызываемые функции производят те же действия, что и одноименные функции исчезающего меню.

3.3. Организация иерархического меню

Для организации иерархического меню необходимо выполнить следующие действия:

  • создать меню, используя make_menu();

  • активизировать меню с помощью pulldown();

  • восстанавливать экран, используя restore_video(), при выходе из каждого меню.

Фреймы меню заполняются в программе один раз. Активизация и восстановление производятся динамически, эти подпрограммы вызываются в узлах иерархии, состоящей из фреймов меню. Управление вызовами производится с помощью операторов switch.

Пусть, например, требуется организовать иерархическое меню с головным фреймом (рис. 3.1), имеющим нулевой номер

Файл

Параметры

Работа

Выход


Рис. 3.1. Головной фрейм

и фреймами (рис. 3.2), меню которых вызываются с помощью выбора опций, соответственно, “Файл”, “Параметры” и “Работа”:

Рис. 3.2. Фреймы меню

Этим фреймам присвоим номера 1, 2 и 3. Это меню мы применим для демонстрации метода Гаусса решения системы линейных уравнений: Ax=B. Опция “Чтение” позволяет заполнять матрицу А и вектор В данными из файла DATA.TXT; “Запись ” предназначена для сохранения матрицы А, вектора В и решения x в файл RESULT.TXT; “Печать” выводит эти данные на принтер; “Матрица А” предназначена для просмотра и корректировки коэффициентов матрицы А, а “Вектор В” – для просмотра и изменения вектора В; “По шагам” выводит промежуточные изменения матрицы А и вектора В; “Непрерывно” выводит сразу решение и конечные значения коэффициентов матрицы А и вектора В.

В программе мы определим списки опций как внешние массивы:

char *main_menu[ ] ={“Файл”, “Параметры”, “Работа”, “Выход”};

char *main_file[ ] ={“Чтение”, “Запись ”, “Печать”};

char *main_rabota[] ={“По шагам”, “Непрерывно”};

char *main_parametry[ ] ={“Матрица А, “Вектор В”};

и фреймы заполняются с помощью операторов:

make_menu (0, main_menu,”фарв”, 4, 0, 0, BORDER,1);

make_menu (1, menu_file,”чзп”, 3, 0, 2, BORDER,0);

make_menu (2, menu_parametry,”мв”, 2, 7, 2, BORDER,0);

make_menu (3, menu_rabota,”шн”, 2, 18, 2, BORDER,0);

а затем вызывается управляющая подпрограмма иерархического меню:

void pd_driver()

{

int choice 1, choice 2; //номера опций

while ((choice 1=pulldown(0))!=-1)

{

switch (choice 1)

{

case 0:

choice 2= pulldown(1);

switch (choice 2)

{

case 0:

/*Прочитать А и В из файла DATA.TXT*/

break;

case 1:

/*Записать А и В в RESULT.TXT*/

break;

case 2:

/*Распечатать А,В и x*/

break;

} restore_video(1);

break;

case 1:

choice 2= pulldown(2);

switch (choice 2)

{

case 0:

/*Редактирование матрицы А*/

break;

case 1:

/*Редактирование вектора В*/

break;

} restore_video(2);

break;

case 2:

choice 2= pulldown(3);

switch (choice 2)

{

case 0:

/*Пошаговая работа*/

break;

case 1:

/*Непрерывная работа*/

break;

} restore_video(3);

break;

case 3: return;

}

} restore_video(0);

}

В общем случае число переменных для номеров опций равно уровню вложенности меню. Управляющая подпрограмма должна быть дополнена выполнением действий, соответствующих листьям дерева иерархического меню.

Дополняя управляющую подпрограмму вызовами функций, выполняющими эти действия, получаем окончательный текст диалоговой программы демонстрации метода Гаусса для решения системы линейных уравнений, разработанной на основе иерархического меню:

#include <stdlib.h>

#include <conio.h>

#include <string.h>

#include <stdio.h>

#include <bios.h>

#include <ctype.h>

#include <math.h>

#define scan_cod 0

#define ascii_cod 1

#define BORDER 1

#define ESC 27

#define REV_VID 0x70

#define NORM_VID 7

#define MAX_FRAME 100

#define TAB 15

#define LEFT 75

#define RIGHT 77

#define ENTER 28

#define UP 72 // стрелка вверх

#define DOWN 80 // стрелка вниз

char far *vid_mem=(char far *)0xb8000000;

struct menu_frame //фрейм меню

{

int startx,endx,starty,endy;

unsigned char *p; /* указатель на информацию экрана */

char **menu; /* указатель на строки меню */

char *keys; /* указатель на HOT KEYS */

int border; /* рамка включено/выключено */

int count; /* число альтернатив */

int active; /* активно ли меню сейчас */

int horizont; /* горизонтальное или вертикальное */

} frame[MAX_FRAME];

float A[5][5],B[5],X[5];

char *main_menu[] ={" Файл "," Параметры "," Работа "," Выход "};

char *menu_rabota[] ={" По шагам "," Непрерывно "};

char *menu_parametry[] ={" Матрица А "," Вектор В "};

char *menu_file[] ={" Чтение "," Запись "," Печать "};

//Прототипы функций

char key_press(int);

void message(char *);

int save_rezult(void);

int open_data(void);

void input_matrix(int,int);

void print_all_matrix(float [5][5],float [5],float[5]);

void field(int,int,int);

void big_field(int);

int make_menu(int, char**, char*, int, int, int, int, int);

void pd_driver();

int pulldown(int);

void display_menu(int);

void draw_border(int);

int get_resp(int);

void save_video(int);

void restore_video(int);

void GaussMethod(int type);

void write_char(int, int, char, int);

void write_string(int, int, char*, int);

int video_mode();

int is_in(char*, char);

void main(void)

{

textattr(0x07);

clrscr();

make_menu(0,main_menu,"фарв",4,0,0,BORDER,1);

make_menu(1,menu_file,"чзп",3,0,2,BORDER,0);

make_menu(2,menu_parametry,"мв",2,7,2,BORDER,0);

make_menu(3,menu_rabota,"шн",2,18,2,BORDER,0);

pd_driver();

clrscr();

}

void pd_driver()

{

int choice1, choice2,

choice3, choice4, selection;

/* активизация окон по мере надобности */

while((choice1 = pulldown(0)) != -1)

{

switch ( choice1 )

{

case 0: // Файл

choice2 = pulldown(1);

switch( choice2 )

{

case 0:

if(open_data())

message("Данные считаны из файла DATA.TXT. Нажмите любую клавишу...");

else

message("Невозможно открыть файл DATA.TXT. Нажмите любую клавишу...");

break;

case 1:

if(save_rezult())

message("Данные записаны в файл REZULT.TXT. Нажмите любую клавишу...");

else

message("Невозможно открыть файл REZULT.TXT. Нажмите любую клавишу...");

break;

case 2:

if(save_rezult())

message("Данные записаны в файл REZULT.TXT. Нажмите любую клавишу...");

else

message("Невозможно открыть файл REZULT.TXT. Нажмите любую клавишу...");

break;

} restore_video(1);

getch();

message("");

break;

case 1: //Параметры

choice3 = pulldown(2);

switch( choice3 )

{

case 0:

message("Редактирование матрицы А (вход в ячейку - /

Enter, выход в меню - Esc)");

restore_video(2);

input_matrix(5,5);

message(""); break;

case 1:

message("Редактирование вектора B (вход в ячейку - /

Enter, выход в меню - Esc)");

restore_video(2);

input_matrix(5,1);

message(""); break;

} restore_video(2); break;

case 2: //Работа

choice4 = pulldown(3);

switch( choice4 )

{

case 0: restore_video(3);GaussMethod(1); break;

case 1: restore_video(3);GaussMethod(0); break;

} restore_video(3); break;

case 3: //Выход

return;

}

}

restore_video(0);

}

/* Высветить меню и получить выбор */

int pulldown(int num)

{

int vmode,choice;

vmode=video_mode();

if((vmode!=2) && (vmode!=3) && (vmode!=7))

{

printf(" должен быть 80 символьный текстовый режим");

exit(1);

}

/* присвоить соответствующий адрес видео памяти */

if(vmode==7) vid_mem=(char far *)0xB0000000;

else vid_mem=(char far *)0xB8000000;

/* узнать активнсть окна */

if(!frame[num].active)

{ /* не активно */

save_video(num);

frame[num].active= 1; /* установить признак активности */

}

if( frame[num].border) draw_border(num);

display_menu(num); /* высветить меню */

return get_resp(num); /* возвратить выбор */

}

/* создание фрейма иерархического меню.

1 если фрейм может быть создан

в противном случае 0 */

int make_menu ( int num, /* номер меню */

char *menu[], /* текст меню */

char *keys, /* горячие клавиши */

int count, /* число альтернатив */

int x, int y, /* левый верхний угол */

int border, /* рамка */

int horizont /* горизонтальное или вертикальное */)

{

register int i,len;

int endx, endy, choice, vmode;

unsigned char *p;

if(num>MAX_FRAME)

{

printf("Слишком много меню");

return 0;

}

if((x>79)||(x<0)||(y>24)||(y<0))

{

printf(" выход за пределы экрана");

return -2;

}

/* вычисление размеров меню*/

len=0;

if(horizont) //если горизонтальное

{

for(i=0;i<count;i++)

len += strlen(menu[i]);

}

else

{

for(i=0;i<count;i++)

if(strlen(menu[i]) > len)

len = strlen(menu[i]);

}

endx=len+x+1;

if(horizont)

endy=y+2;

else

endy=count+y+1;

if((endx>79) || (endy>24))

{

printf(" Выход за пределы экрана");

return -2;

}

/* размещение памяти для видеобуфера */

p=(unsigned char *)malloc((len+2)*(count+2)*2);

if(!p) exit(1); /* Вы можете здесь сами обработать ошибку */

/* создание фрейма */

frame[num].startx = x;

frame[num].endx = endx;

frame[num].starty = y;

frame[num].endy = endy;

frame[num].p = p;

frame[num].menu = (char **) menu;

frame[num].border = border;

frame[num].keys = keys;

frame[num].count = count;

frame[num].active = 0;

frame[num].horizont = horizont;

return 1;

}

/* высвечивание меню на своем месте */

void display_menu(int num)

{

char **m;

register int i, x, y;

x = frame[num].startx+1;

y = frame[num].starty+1;

m = frame[num].menu;

if(frame[num].horizont)

{

for(i=0;i<frame[num].count;i++)

{

write_string(x,y,m[i],NORM_VID);

x+=strlen(m[i]);

}

}

else

for(i=0;i<frame[num].count;i++,y++)

write_string(x,y,m[i],NORM_VID);

}

/* рисование рамки меню*/

void draw_border(int num)

{

register int i;

int x1 = frame[num].startx;

int x2 = frame[num].endx;

int y1 = frame[num].starty;

int y2 = frame[num].endy;

write_char(x1, y1, '+', NORM_VID);

write_char(x2, y1, '+', NORM_VID);

write_char(x1, y2, '+', NORM_VID);

write_char(x2, y2, '+', NORM_VID);

for(i=x1+1; i<x2; i++)

{

write_char(i, y1, '-', NORM_VID);

write_char(i, y2, '-', NORM_VID);

}

for(i=y1+1;i<y2;i++)

{

write_char(x1, i,'¦', NORM_VID);

write_char(x2, i,'¦', NORM_VID);

}

}

/* сохранение части экрана с использованием

прямого доступа к видеопамяти */

void save_video(int num)

{

register int i, j;

char far *v, far *t;

char *buf_ptr;

buf_ptr= frame[num].p;

v = vid_mem;

for(i=frame[num].starty;i<=frame[num].endy;i++)

{

for(j=frame[num].startx; j<=frame[num].endx; j++)

{

t = v+i*160+j*2; // вычисляем адрес

*buf_ptr++ = *t++; // записываем в буфер символ

*buf_ptr++ = *t; // записываем в буфер атрибут

*(t-1) = ' '; // очистка окна

}

}

}

/* восстановление части экрана */

void restore_video(int num)

{

register int i,j;

char far *v,far *t; // временные переменные

char *buf_ptr;

buf_ptr=frame[num].p;

v = vid_mem; // адрес начала видеопамяти

t = v;

for(i=frame[num].starty; i<=frame[num].endy; i++)

{

for(j=frame[num].startx; j<=frame[num].endx; j++)

{

v = t;

v += i*160+j*2; // вычисление адреса

*v++ = *buf_ptr++; // восстановление из буфера символа

*v = *buf_ptr++; // восстановление из буфера атрибута

}

}

frame[num].active= 0;

}

/* вывод строки с определенным атрибутом */

void write_string(int x, int y, char* p, int attrib)

{

register int i;

char far *v; //адрес символа

v = vid_mem; //в v помещаем адрес начала видеопамяти

v += y*160+x*2; //вычисляем адрес начала строки в видеопамяти

for(i=y;*p;i++)

{

*v++ = *p++; //записываем в видеопамять символ

*v++ = attrib; //записываем в видеопамять атрибут

}

}

/* запись символа с определенным атрибутом */

void write_char(int x, int y, char ch, int attrib)

{

char far *v; //адрес символа

v = vid_mem; //в v помещаем адрес начала видеопамяти

v += y*160+x*2; //вычисляем адрес символа в видеопамяти

*v++ = ch; //записываем в видеопамять символ

*v = attrib; //записываем в видеопамять атрибут

}

/* ввести выбор пользователя */

int get_resp(int num)

{

char** m;

char* keys;

register int i, x, y, count, horizont;

int xx; //координата x в зависимости от горизонтальности меню

x = frame[num].startx+1;

y = frame[num].starty+1;

count = frame[num].count;

horizont = frame[num].horizont;

m = frame[num].menu;

keys = frame[num].keys;

union inkey

{

char ch[2];

int i;

} c;

int arrow_choice=0, key_choice;

/* осветить первый выбор */

write_string(x, y, m[0], REV_VID);

for(;;)

{

while(!bioskey(1)); // ждать нажатия

c.i=bioskey(0);

/* вернуть выбор в нормальный режим */

if(horizont)

{

xx = x;

if(arrow_choice)

for(i=0; i<arrow_choice; i++)

xx +=strlen(m[i]);

write_string(xx, y, m[arrow_choice], NORM_VID);

}

else

write_string(x, y+arrow_choice, m[arrow_choice], NORM_VID);

if(c.ch[0]) // обычная клавиша

{

// горячая клавиша?

key_choice = is_in(keys,tolower(c.ch[0]));

if(key_choice) return key_choice-1;

switch(c.ch[0])

{

case '\r' : return arrow_choice;

case ' ' : arrow_choice++; break;

case ESC : return -1; // выйти

}

}

else // специальная клавиша

{

if(horizont)

switch(c.ch[1])

{

case LEFT : arrow_choice--; // стрелка вниз

break;

case RIGHT : arrow_choice++; // стрелка вверх

break;

}

else

switch(c.ch[1])

{

case UP : arrow_choice--; // стрелка вниз

break;

case DOWN: arrow_choice++; // стрелка вверх

break;

}

}

/* осуществить цикличность меню */

if(arrow_choice==count) arrow_choice=0;

if(arrow_choice<0) arrow_choice=count-1;

/* подсветить выбранную опцию */

if(horizont)

{

xx = x;

if(arrow_choice)

for(i=0; i<arrow_choice; i++)

xx +=strlen(m[i]);

write_string(xx, y, m[arrow_choice], REV_VID);

}

else

write_string(x, y+arrow_choice, m[arrow_choice], REV_VID);

}

}

//Функция, возвращающая ASCII или скан-код клавиши

char key_press(int type)

{

asm {

xor ah,ah

int 0x16

}

if(type) return _AL;

return _AH;

}

//Функция для вывода сообщения внизу экрана

void message(char *str)

{

for(int i=0;i<80;i++) write_char(i,24,' ',0x4E);

write_string(0,24,str,0x4E);

}

//Функция для ввода матрицы или вектора

void input_matrix(int string,int column)

{

char press;

_setcursortype(_NORMALCURSOR);

int i=0,j=0,norm_attr=0x1A;

float matrix[5][5];

char *str;

int pos_str=1,pos_col=1;

field(string,column,norm_attr);

if(column==1) //вектор

for(i=1;i<=string;i++)

{

matrix[i-1][0]=B[i-1];

gotoxy(1,i*2+3);

printf("%.2f",matrix[i-1][0]);

}

else //матрица

for(i=1;i<=string;i++)

for(j=1;j<=column;j++)

{

matrix[i-1][j-1]=A[i-1][j-1];

gotoxy(j*9-8, i*2+3);

printf("%.2f",matrix[i-1][j-1]);

}

while(1)

{

gotoxy(pos_col*9-8,pos_str*2+3);

press=key_press(scan_cod);

switch(press)

{

case 1:

if(column==1) for(i=0;i<string;i++) B[i]=matrix[i][0];

else

for(i=0;i<string;i++)

for(j=0;j<column;j++) A[i][j]=matrix[i][j];

_setcursortype(_NOCURSOR); field(string,column,0); return;

case DOWN: if(++pos_str>string) pos_str=1; break;

case RIGHT: if(++pos_col>column) pos_col=1; break;

case TAB: if(++pos_col>column) pos_col=1; break;

case LEFT: if(--pos_col<1) pos_col=column; break;

case UP: if(--pos_str<1) pos_str=string; break;

case ENTER:

write_string(wherex()-1,wherey()-1," ",norm_attr);

i=0;

while(1)

{

press=key_press(ascii_cod);

if(press==27)

{

_setcursortype(_NOCURSOR);

field(string,column,0);

return;

}

if(press=='\r' || press=='\t') { str[i]='\0' ; i=0; break; }

if(press>=0x30 && press<=0x39 || press=='.')

{

write_char(wherex()-1,wherey()-1,press,norm_attr);

gotoxy(wherex()+1,wherey());

str[i]=press;

if(++i>7) { str[i]='\0' ; i=0; break; }

}

}

matrix[pos_str-1][pos_col-1]=atof(str);

if(++pos_str>string) pos_str=1; break;

}

}

}

//Функция прорисовки поля для одной матрицы или вектора

void field(int string,int column,int field_attr)

{

for(int i=1; i<=column; i++)

for(int j=1; j<=string; j++)

write_string(i*9-9,j*2+2," ",field_attr);

}

//Функция прорисовки поля для одной матрицы и двух векторов

void big_field(int field_attr)

{

for(int i=1; i<=5; i++)

for(int j=1; j<=5; j++)

write_string(i*9-9,j*2+2," ",field_attr);

for(i=1;i<=5;i++)

{

write_string(50,i*2+2," ",field_attr);

write_string(64,i*2+2," ",field_attr);

}

}

//Функция вывода на экран матрицы и двух векторов

void print_all_matrix(float matrix[5][5],

float vector_1[5],

float vector_2[5])

{

big_field(0x1A);

for(int i=1; i<=5; i++)

for(int j=1; j<=5; j++)

{

gotoxy(i*9-8,j*2+3);

printf("%.3f",matrix[j-1][i-1]);

}

for(i=1; i<=5; i++)

{

gotoxy(51,i*2+3);

printf("%.3f",vector_1[i-1]);

gotoxy(65,i*2+3);

printf("%.3f",vector_2[i-1]);

}

}

//Функция вычисления вектора Х

void GaussMethod(int type)

{

int i,j; //счетчики циклов

float As[5][5], Bs[5];

for (i=0;i<5;i++)

{

Bs[i]=B[i];

for (j=0;j<5;j++) { As[i][j]=A[i][j]; };

};

//Решение системы уравнений

//k-счетчик циклов

//numb-номер строки с ведущим элементом

//max-максимальный по модулю элемент непреобразованного столбца

//str,bstr- используются при перестановке строк

//L-коэффициент преобразования

int numb=0, k;

float max, str, bstr, L;

// Приведение матрицы к U-виду

for (j=0;j<4;j++)

{

max=fabs(A[j][j]);

numb=j;

// Определение максимального элемента в столбце

for (i=j;i<5;i++)

if (max<fabs(A[i][j]))

{ max=fabs(A[i][j]); numb=i; };

// если максимум - недиагональный элемент, то_

if (numb!=j)

{

//_замена строк

for (i=0;i<5;i++)

{

str = A[numb][i];

A[numb][i]= A[j][i];

A[j][i] = str;

};

bstr = B[numb];

B[numb]= B[j];

B[j] = bstr;

};

// преобразование столбца

for (i=j+1;i<5;i++)

{

L = -(A[i][j]/A[j][j]); // вычисление коэффициента

A[i][j]= 0.0;

// обнуление элемента текущего столбца

for (k=j+1;k<5;k++) { A[i][k]=A[i][k]+A[j][k]*L; };

// и вычисление последующих в строке

B[i] = B[i]+B[j]*L;

};

};

// Решение системы линейных уравнений

for (j=4;j>=0;j--)

{

X[j]=B[j]/A[j][j];

if (j!=3)

for (i=4;i>j;i--) {X[j]=X[j]-A[j][i]*X[i]/A[j][j];};

if(type)

{

print_all_matrix(A,B,X);

message("Для продолжения нажмите любую клавишу...");

getch();

}

};

for (i=0;i<5;i++)

{

B[i]=Bs[i];

for (j=0;j<5;j++)

{

A[i][j]=As[i][j];

};

};

message("Расчет окончен");

print_all_matrix(A,B,X);

getch();

big_field(0);

}

//Функция сохранения результата в файл "REZULT.TXT"

int save_rezult(void)

{

FILE *stream;

stream = fopen("rezult.txt", "w+");

if(stream==NULL) return 0;

fprintf(stream,"Matrix A:\n\n");

for(int i=0;i<5;i++)

{

for(int j=0;j<5;j++)

fprintf(stream,"%f\t",A[i][j]);

fprintf(stream,"\n");

}

fprintf(stream,"\nVector B:\n\n");

for(i=0;i<5;i++) fprintf(stream,"%f\n",B[i]);

fprintf(stream,"\n\nVector X:\n\n");

for(i=0;i<5;i++) fprintf(stream,"%f\n",X[i]);

fclose(stream);

return 1;

}

//Функция чтения данных из файла "DATA.TXT"

int open_data(void)

{ int i=0,j=0,k=0;

char *str;

FILE *stream;

stream = fopen("data.txt", "r");

if(stream==NULL) return 0;

while(k<2)

if(fgetc(stream)=='\n') k++;

k=0;

for(i=0;i<5;i++)

for(j=0;j<5;j++)

{

int bool=1;

while(1)

{

str[k]=fgetc(stream);

if(str[k]=='\t')

{

str[k]='\0';

k=0; break;

}

k++;

if(str[k]=='\n') bool=0;

}

if (bool) A[i][j]=atof(str);

}

while(k<4)

if(fgetc(stream)=='\n') k++;

k=0;

for(i=0;i<5;i++)

{

while(1)

{

str[k]=fgetc(stream);

if(str[k]=='\n')

{

str[k]='\0';

k=0; break;

}

k++;

}

B[i]=atof(str);

}

fclose(stream);

return 1;

}

/* запрос текущего видеорежима */

int video_mode()

{

union REGS r;

r.h.ah = 15; /* получить режим */

return int86(0x10,&r,&r) & 255;

}

/* проверка принадлежности символа к строке s */

int is_in(char* s, char c)

{

register int i;

for(i=0; *s; i++)

if(*s++ == c) return i+1;

return 0;

}

Например, при выборе опции “Матрица А” (рис 3.3) на экран будут выведены коэффициенты матрицы А:

Рис. 3.3. Решение системы линейных уравнений

методом Гаусса с использованием иерархического меню

Для того чтобы изменить значение коэффициента, надо установить на нем курсор и нажать клавишу <ENTER>, затем ввести значение и вновь нажать <ENTER>.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]