Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 11, средняя оценка - 4.64
Darthriddikc
10 / 10 / 0
Регистрация: 23.12.2012
Сообщений: 45
#1

Меню на консоли - C++

19.12.2013, 02:07. Просмотров 1734. Ответов 2
Метки нет (Все метки)

Здравствуйте! Изучаю C++, для практики ради делаю консольное меню через класс.
Может быть мне, пока что, ещё далеко до претендента на гуру по адекватной реализации алгоритмов
Вот, как я это реализовал...

classias.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#include <iostream>
#include <conio.h>
#include <windows.h>
using namespace std;
 
#ifndef CPP_MENU
#define CPP_MENU
 
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
 
class Menu{
 
///////////////////////// * СТЕК * ///////////////////////////
    // Структура стека и функции работы с ним, хранит предыдущие директории(меню)
    static struct STACK_DIR{
        static int num;
        Menu *elem;
        STACK_DIR *last;
    }*stackDir;
 
    void push(STACK_DIR* &stack, Menu* i){
        STACK_DIR *last_stack=stack;
        stack=new STACK_DIR;
        STACK_DIR::num++;
        stack->elem=i;
        stack->last=last_stack;
    }
 
    Menu* pop(STACK_DIR* &stack){
        Menu *pop_elem=stack->elem;
        STACK_DIR *temp=stack;
        stack=stack->last;
        delete temp;
        STACK_DIR::num--;
        return pop_elem;
    }
//////////////////////////////////////////////////////////////
 
    // LINES_Data - структура данных одной строки в объекте
    struct LINES_Data{
        char name[32]; // Название строки
        Menu *nextDir; // Куда эта строка ведёт
    }*lineData;
 
    static Menu *delLines; // для "подтирания" оставшихся символов предыдущего меню
    unsigned short lines; // число строк в одной директиве
    short position; // позиция, где на данный момент находится выбор
 
    // GoToXY - метод который будет устанавливать "каретку" на поле консоли (x-столбец y-строка)
    // по сути с помощью него будет очищаться экран от старого меню, но в отличии от CLS будет замещать старое меню новым
    void GoToXY(unsigned x, unsigned y){
        COORD coord = { static_cast<SHORT>(x), static_cast<SHORT>(y) };
        SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
    }
 
public:
 
    static unsigned Y_Console_pos; //положение "каретки" по X
    static unsigned X_Console_pos; //положение "каретки" по Y
 
    //В конструктор задаётся число строк менюшки и 2 необязательных параметра - положение X Y (по умолчанию 0,0)
    Menu(unsigned lines, unsigned X_Console_pos=Menu::X_Console_pos, unsigned Y_Console_pos=Menu::Y_Console_pos){
        Menu::Y_Console_pos=Y_Console_pos;
        Menu::X_Console_pos=X_Console_pos;
        position=0;
        char ch_i[4];
        Menu::lines=lines;
        lineData=new LINES_Data[lines];
        for(int i=0; i<lines; i++){
            strcpy(lineData[i].name,"ITEM_");
            sprintf(ch_i,"%d",i+1);
            strcat(lineData[i].name,ch_i);
            lineData[i].nextDir=this;
        }
    }
    ~Menu(){
        delete []lineData;
    }
 
    // startMenu - запуск меню
    void startMenu(){
        int key; // код клавиши
        if(delLines){
            for (int i=0; i<delLines->lines; i++){
                GoToXY(X_Console_pos,Y_Console_pos+i);
                for(int j=0; j<strlen(delLines->lineData[i].name); j++)
                    cout<<' ';
                cout<<endl;
            }
        }
        while(1){
            if(position<0)
                position=lines-1;
            if(position>=lines)
                position=0;
            for (int i=0; i<lines; i++){
                GoToXY(X_Console_pos,Y_Console_pos+i);
                if(i==position)
                    SetConsoleTextAttribute(hConsole, 0+(7<<4));
                cout<<lineData[i].name<<endl;
                SetConsoleTextAttribute(hConsole, 7+(0<<4));
            }
            key=_getch();
            if(key==27){ // Esc
                if(STACK_DIR::num){
                    delLines=this;
                    pop(stackDir)->startMenu();
                }
                break;
            }
            if(key==224){
                key=_getch();
                switch (key){
                case 72: // стрелка вверх
                    position--;
                    break;
                case 80: // стрелка вниз
                    position++;
                    break;
                }
            }
            if(key==13){ // Enter
                if(!lineData[position].nextDir)
                    break;
                if(lineData[position].nextDir!=this){
                    delLines=this;
                    if(STACK_DIR::num && stackDir->elem==lineData[position].nextDir){
                        pop(stackDir)->startMenu();
                        break;
                    }
                    push(stackDir,this);
                    lineData[position].nextDir->startMenu();
                    break;
                }
            }
        }
    }
 
    // lineInit - метод инициализации строки (номер строки, куда она пошлёт, имя строки)
    void lineInit(int i, Menu* nextDir, char *name=0){
        if(i>lines-1){
            cerr<<"Line "<<i<<" Error! Overflowing lines! Max="<<lines-1<<endl;
        }
        else{
            if(name)
                strcpy(lineData[i].name,name);
            lineData[i].nextDir=nextDir;
        }
    }
};
 
unsigned Menu::X_Console_pos=0;
unsigned Menu::Y_Console_pos=0;
int Menu::STACK_DIR::num=0;
Menu::STACK_DIR *Menu::stackDir=0;
Menu *Menu::delLines=0;
 
#endif
Ну и как это работает на примере
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include "classias.h"
 
int main(){
    Menu Main(5,35,5), NewGame(4), Options(3), Keyboard(5), About(1), Score(2);
 
    Main.lineInit(0,&NewGame,      "NEW GAME");
    Main.lineInit(1,&Options,      "OPTIONS");
    Main.lineInit(2,&About,        "ABOUT");
    Main.lineInit(3,&Score,        "SCORE");
    Main.lineInit(4,0,             "EXIT");
 
    NewGame.lineInit(0,&NewGame,   "EASY");
    NewGame.lineInit(1,&NewGame,   "MEDIUM");
    NewGame.lineInit(2,&NewGame,   "HARD");
    NewGame.lineInit(3,&Main,      "BACK");
 
    Options.lineInit(1,&Keyboard,  "KEYBOARD");
    Keyboard.lineInit(4,&Options,  "BACK");
    Options.lineInit(2,&Main,      "BACK");
 
    About.lineInit(0,&Main,        "BACK");
 
    Score.lineInit(1,&Main,        "BACK");
 
    Main.startMenu();
    return 0;
}
В этом меню, пока что, можно только "гулять" из директории в директорию (то есть передавать в nextDir указатель на объект Menu)... И вот я запоролся на вроде бы тривиальной задачке, как реализовать переход к какой-нибудь функции и чтоб это было "красиво", в смысле к примеру чтоб можно было сделать так:
C++
1
2
3
4
5
6
7
void func1( ... ){
    /* . . . */
};
 
/* . . . */
 
NewGame.lineInit(0,func1( ... ),   "EASY");
Ну и естественно желательно чтоб это всё также оставалось храниться в структуре LINES_Data.
У меня есть предположения, что это можно реализовать как-то через шаблоны (template), но для этого потребуется "шаблонить" LINES_Data, а значит, при создании объекта этой структуры, нужно заранее указывать типы, но в моём случае получается, что, до инициализации строки меню, ещё неизвестно какой тип будет у объекта структуры. Правда я совсем недавно изучил шаблоны, и может быть многое про них не знаю, к примеру можно ли как-то обойти объявление типов при объявлении объекта... Но главный мой вопрос этой темы я уже оговорил выше

Добавлено через 8 часов 59 минут
Попробовал всячески через шаблоны, только запутался
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
19.12.2013, 02:07
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Меню на консоли (C++):

Меню в консоли - C++
есть код для менюшки, по идее при нажатии стрелок вверх или вниз, должен передвигаться флажок -&gt; , но почему то не передвигается,...

Меню в консоли - C++
По условию нужно сделать что-то вроде меню в консоли. Чисто теоретически порядок знаю, но с реализацией проблемы((( в while массив из 5...

Меню в консоли - C++
Меня интересует вот что: зачем в функции int menu(); вот это условие code=getch(); if (code==224) ...

Оригинальное меню в консоли - C++
Доброго вечера, помогите разобраться с некоторым кодом, в котором содержится интересное консольное меню с помощью goto xy. Искал в нэте...

Работа с меню в консоли - C++
я написал программу #include&lt;iostream.h&gt; #include&lt;conio.h&gt; #include&lt;stdlib.h&gt; #include&lt;iomanip.h&gt; #include&lt;system.hpp&gt; int...

Организация меню в консоли - C++
всем доброе время суток необходимо организованить меню: Для выбора метода вычисления корня уравнения использовать меню, разработанное с...

2
ПерС
371 / 287 / 89
Регистрация: 05.11.2013
Сообщений: 820
Записей в блоге: 5
Завершенные тесты: 1
19.12.2013, 12:22 #2
а просто указатель на функцию не пробовал?
пример из сети:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <conio.h>
#include <stdlib.h>
typedef unsigned char byte;
typedef void (*FUN)(void);
 //Указатель на функцию обработки
 //пункта меню - указатель на объекты вида void Функция(void)
 
struct MENU { //например, опишем простейшее меню
 int x,y; // Позиция на экране пункта меню
 byte *str; // Строка текста меню
 FUN sf; // Указатель на функцию
         // обработки пункта
};
 
/* код функций обработки пункта меню */
 
void Exit () { exit (0); }
 
void Start () {  }
 
/* Код функций вывода и поддержки меню */
 
void DrawMenu (MENU *m) {
 gotoxy(m->x,m->y);
 cprintf ("%s",m->str);
}
#define ITEMS 2
void main () {
 MENU Menu[ITEMS]={
  { 1, 1, "Начать", Start },
  {10, 1, "Выход", Exit }
 };
 clrscr ();
 for (int i=0; i<ITEMS; i++)
  DrawMenu (&Menu[i]);
 Menu[0].sf(); /*Вызвали Start() косвенно, через указатель на функцию*/
}
0
Darthriddikc
10 / 10 / 0
Регистрация: 23.12.2012
Сообщений: 45
19.12.2013, 15:39  [ТС] #3
Цитата Сообщение от ПерС Посмотреть сообщение
а просто указатель на функцию не пробовал?
Ну я так и хочу, через указатель, попасть на стороннюю функцию в конечном итоге, но в вашем примере нормально перейти можно, только к сторонней функции, так как он очень упрощённый, а если, как в моём случае, это может быть ещё и сам объект класса меню (например, реализовать переход к следующему меню), тогда каждому методу вывода меню, у каждого объекта, нужно делать обёртку, которая помимо того, что должна возвращать метод, должна ещё менять некоторые значения элементов класса и подчас частные, а значит ещё плюс эту обёртку нужно объявить другом класса.
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
19.12.2013, 15:39
Привет! Вот еще темы с ответами:

Меню в консоли - Ввод данных - C++
Доброй ночи Просьба не судить строго мой код - я только учусь! Вот код меню: #include &lt;conio.h&gt; #include &lt;stdio.h&gt; #include...

Создание меню в консоли (не контекстное) - C++
Доброй ночи, кому вечеру и утру в Америке. Сижу на втором курсе и еще до такой темы не доходили, но в ней сейчас нужда. Ой, забыл саму...

Реализация разветвляющегося меню в консоли - C++
Привет!, Помогите написать код что бы При Нажатие клавиши 1 выполнился код после if (option == 1) #include &lt;iostream&gt; using...

Бесконечное появление меню в консоли - C++
При попытке добавления записи через меню, меню начинает появляться в бесконечном количестве в консоли. Как исправить? Вроде проблема в...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
3
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru