3. Иерархическое меню


Добавил:DMT
Дата создания:5 апреля 2008, 15:08
Дата обновления:5 апреля 2008, 15:10
Просмотров:10277 последний ---
Комментариев: 0

3. ИЕРАРХИЧЕСКОЕ МЕНЮ

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

 

3.1. Фреймы меню

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

struct menu_frame

{

int startx, starty, endx, endy ; // координаты углов

unsigned char * p ; //указатель на область сохранения

char * menu [] ; //массив строк подменю

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

int count ; // число опций

int active ; // 1- активно меню, 0 – нет

int horizont ; // 1- горизонтальная линейка

// 0 – вертикальное меню

} frame [ MAX _ FRAME ];

если frame[i]. horizont = 0 , то меню выводится в виде строк текста, расположенных сверху вниз. Если frame[i]. horizont = 1 , то опции меню расположены в одну линию, слева направо.

Всем меню, входящим в иерархическое меню, присваиваются номера. Меню, имеющему номер i , ставится в соответствие i - й элемент массива фреймов. В главной программе поля фреймов заполняются с помощью функции, первым аргументом которой является номер фрейма, а остальные аналогичны аргументам функции popup() исчезающего меню. Последний параметр указывает, будет ли меню горизонтальным. Эта функция определяет также свободную память для сохранения области вывода.

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((endx > 79)||(endy > 24))

{

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

return –2;

}

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

//захват свободной памяти

if (! p )

{

printf (“Не хватило памяти”);

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;

}

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 >.

3.4. Всплывающие окна

Современные диалоговые системы строятся на основе всплывающих окон. Всплывающим окном называется часть экрана, используемая для ввода и вывода текстовых и графических данных. Перед появлением всплывающего окна на экране текущее содержимое экрана сохраняется, а после его исчезновения содержимое экрана восстанавливается.

Разработка функций, управляющих всплывающими окнами, является сложной задачей из-за необходимости обеспечения запрета для прикладной программы осуществлять вывод за границы окна. Поскольку размеры окна могут изменяться без “сообщения” об этом прикладной программе, то именно функции управления окнами, а не прикладная программа, должны «предохранить» от выхода за границы окна. Следовательно, все обычные функции ввода и вывода для консоли должны быть заменены функциями, ориентированными на окна.

Всплывающие окна используются следующим образом. Каждая отдельная задача программы использует свое собственное окно. При запуске задачи активизируется и ее окно. При завершении работы задачи ее окно удаляется. Если же выполнение задачи прерывается, то окно остается активным, и на экран могут быть выведены окна других задач.

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

 

struct window_frame

{

int startx, starty, endx, endy; // позиция окна

int curx , cury ; //текущая позиция курсора в окне

unsigned char * p ; //указатель буфера сохранения

char * header ; //заголовок (имя) окна

int border ; //1 – рамка есть, 0 – рамки нет

int active ; //1 – окно активно, 0 – неактивно

} frame [MAX_FRAME];

 

Для записи в окно используются специальные функции ввода и вывода, ориентированные на окна.

Для создания окна определяется функция

 

int make_window ( int num, // номер окна

char * header , //текст заголовка

int startx, int starty, // левый верхний угол

int endx, int endy, // правый нижний угол

int border); // присутствие рамки

 

функция возвращает единицу, если окно не может быть создано.

Окно активируется при помощи функции:

void window(int num);

которая сохраняет область вывода, делает окно активным и выводит окно на экран.

Функция

void deactivate(int num);

деактивирует окно.

 


В заключени е приведём прототипы оконных функций ввода-вывода:

 

int window _ xy ( int num , intx , inty ); //установка курсора в позицию (x,y)

int window_getche(int num); // аналогично getche()

void window_gets(int num, char *s); // чтение строки в s

int window_putchar(int num, char ch); // вывод символа

int window_puts(int num, char *str); // вывод строки

void window_cls(int num); // очистка окна

void window _ cleol ( int num ); //очистка строки от текущей //позиции до конца строки

int window _ upline ( int num ); //перемещает курсор на одну //строку вверх

int window _ downline ( int num ); //перемещает курсор на одну //строку вниз

int window _ bksp ( int num ); //стирает предшествующий символ

 

up