Возврат после выполнения программы в первое в меню - C (СИ)
Формулировка задачи:
Есть задача с меню. Необходимо сделать так, что бы после выполнения программы, программа предлагала вернуться в начальное меню, либо завершить программу. Я предполагаю выбор (вернуться в меню или завершить программу) сделать через switch case, но каким образом реализовать возврат в первое меню? Заранее спасибо)
Решение задачи: «Возврат после выполнения программы в первое в меню»
textual
Листинг программы
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
enum CONSTANTS {
MAX_ITEMS = 10
};
struct menu_item;
struct menu;
typedef struct menu menu;
typedef struct menu_item menu_item;
typedef void(*command)(const menu_item*);
/// Структура "элемент меню"
struct menu_item {
/// заголовок
char title[20];
/// команда для выполнения
command cmd;
/// указатель на подменю
menu* submenu;
};
/// Структура "меню"
struct menu {
/// количество элементов в меню
int count;
/// список элементов
menu_item* items[MAX_ITEMS];
/// указатель на родительское меню
menu* parent;
};
/// базовый "конструктор" для объекта "элемент меню"
menu_item* new_item(const char* title);
/// конструктор для элемента с коммандой
menu_item* new_command(const char* title, command cmd);
/// конструктор для новой менюшки
menu* new_menu(menu* parent);
/// добавляет команду в меню
menu_item* add_command(menu* self, const char* title, command cmd);
/// Добавляет подменю
menu* add_submenu(menu* self, const char* title);
/// Цикл опроса менюшек
void dispatch_menu(menu*);
/// освобождает память
void delete_menu(menu*);
/// Создает структуру меню для данной программы
menu* make_main();
int main() {
menu* main_menu;
// создаем менюшку
main_menu = make_main();
// запускаем цикл опроса
dispatch_menu(main_menu);
// удаляем меню
delete_menu(main_menu);
return 0;
}
//--------------------- тестовые команды для пунктов меню ---------//
void cmd_test1(const menu_item* item) {
fprintf(stdout,
"This is test for `%s` menu item\n",
item->title
);
}
void cmd_test2(const menu_item* item) {
fprintf(stdout,
"This is other test for `%s` menu item\n",
item->title
);
}
void cmd_test3(const menu_item* item) {
fprintf(stdout,
"This is test for `%s` menu item\n",
item->title
);
}
menu* make_main() {
menu* self, *sub;
self = new_menu(NULL);
add_command(self, "First", cmd_test1);
add_command(self, "Second", cmd_test2);
sub = add_submenu(self, "Sub menu test");
add_command(sub, "Item in submenu", cmd_test3);
return self;
}
//----------------- Функции для работы с меню ---------//
menu* new_menu(menu* parent) {
menu* self;
self = (menu*)calloc(1, sizeof(menu));
self->parent = parent;
return self;
}
menu_item* new_item(const char* title) {
menu_item* self;
self = (menu_item*)calloc(1, sizeof(menu_item));
strcpy(self->title, title);
return self;
}
menu_item* new_command(const char* title, command cmd) {
menu_item* self;
self = new_item(title);
self->cmd = cmd;
return self;
}
menu_item* add_command(menu* self, const char* title, command cmd) {
menu_item* item = NULL;
if(self->count < MAX_ITEMS) {
item = self->items[self->count] = new_command(title, cmd);
self->count ++;
}
return item;
}
menu* add_submenu(menu* self, const char* title) {
menu* submenu = NULL;
menu_item* item = NULL;
if(self->count < MAX_ITEMS) {
item = self->items[self->count] = new_item(title);
submenu = item->submenu = new_menu(self);
self->count ++;
}
return submenu;
}
void show_item(const menu_item*, int);
void show_menu(const menu*);
int have_submenu(const menu_item* self) {
return !!(self->submenu);
}
int is_submenu(const menu* self) {
return !!(self->parent);
}
int enter(const menu* self, const char* message) {
int id, ok;
do {
fputs(message, stdout);
fscanf(stdin, "%d", &id);
ok = id == MAX_ITEMS;
ok = ok || ((id >= 0) && (id < self->count));
}
while(!ok);
return id;
}
void dispatch_menu(menu* self) {
int id = 0;
int go = 1;
command cmd;
do {
// выводим меню
show_menu(self);
// запрашиваем ответ
id = enter(self, "Enter choose > ");
switch (id) {
case MAX_ITEMS: { // выбран возврат или выход
go = is_submenu(self);
if (go) {
// переход в родительское меню
self = self->parent;
}
} break;
default: { // выбран пункт меню
cmd = self->items[id]->cmd;
if (cmd) {
// выполним команду, если она задана
cmd(self->items[id]);
}
if (have_submenu(self->items[id])) {
// переход в подменю, если оно есть
self = self->items[id]->submenu;
}
}
}
}
while (go);
}
char submenu_sign(const menu_item* self) {
return (
have_submenu(self) ? '>' : ' '
);
}
void show_item(const menu_item* self, int id) {
fprintf(stdout,
" %d - %s %c\n",
id,
self->title,
submenu_sign(self)
);
}
void show_menu(const menu* self) {
int id = 0;
menu_item* it = NULL;
if (!self) return;
while (id < MAX_ITEMS) {
it = self->items[id];
if (!it) {
break;
}
show_item(it, id);
++id;
}
fprintf(stdout,
"%d - %s\n",
MAX_ITEMS,
is_submenu(self) ? "go back" : "exit"
);
}
void delete_menu(menu* self) {
int id = 0;
menu_item* it = NULL;
if (!self) return;
while (id < MAX_ITEMS) {
it = self->items[id];
if (!it) {
break;
}
delete_menu(it->submenu);
free(it);
++id;
}
free(self);
}