我正在寻找一种实现控制台菜单的方法,然后我发现了这一点 an answer from LXSoft on "How to write a console menu in ANSI/ISO C?" 所以我尝试使用Visual Studio 2017在我的代码中实现它
代码:
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <windows.h>
// LXSoft
// mod: cui/menu_021
// stdarg.h -> used for variable list of arguments (va_list, va_start ...)
// windows.h -> used for Sleep function, for *nix use unistd.h
typedef unsigned short int usint_t;
// Menu function prototype
int menu(char* name, char* prefix, char* cursor, usint_t orientation,
usint_t padding, usint_t start_pos, usint_t delay,
usint_t num_childs, ...);
int main()
{
int exit;
do {
exit = 1;
int response = menu("List des commandes", "-", "-->", 1, 3, 1, 0, 2,
"1- Ajouter un etudiant (ou un ensemble d'etudiants)",
"2- exit");
printf("\n");
switch (response)
{
case 1:
// doSomethingFoo1();
exit = 0;
break;
case 2:
//doSomethingFoo2();
exit = 1;
break;
default:
exit = 0;
}
printf("\nYour choice is: %d", response);
} while (!exit);
return 0;
}
// Menu implementation
int menu
(
char *name, // Menu name (eg.: OPTIONS)
char *prefix, // Menu prefix (eg.: [*])
char *cursor, // Menu cursor (eg.: ->)
usint_t orient, /*
* Menu orientation vertical or horzontal.
* 0 or false for horizontal
* 1 or true for vertical
*/
usint_t padding, // Menu childrens padding (eg.: 3)
usint_t start_pos, // Menu set active child (eg.: 1)
usint_t delay, // Menu children switch delay
usint_t childs, // Number of childrens
... /*
* Variable list of arguments char* type.
* Name of the childrens.
*/
)
{
va_list args;
int tmp = 0, pos;
char chr=0;
usint_t opt = start_pos;
char* format = malloc
(
(
strlen(name) + strlen(prefix) + strlen(cursor) +
3 + /* menu suffix (1 byte) and backspace (2 bytes) */
(2 * childs) + /* newline (2 bytes) times childs */
(padding*childs) + /* number of spaces times childs */
childs * 60 /* children name maxlen (15 bytes) times childs*/
) * sizeof(char)
);
do
{
if (tmp != 0)chr = _getch();
if (chr == 0x48 || chr == 0x4B)
(opt > 1 && opt != 1) ? opt-- : (opt = childs);
else if (chr == 0x50 || chr == 0x4D)
(opt >= 1 && opt != childs) ? opt++ : (opt = 1);
else {/* do nothing at this time*/ }
strcpy(format, "");
strcat(format, prefix);
strcat(format, name);
strcat(format, ":");
va_start(args, childs);
for (tmp = 1; tmp <= childs; tmp++)
{
(orient) ? strcat_s(format, SizeFormat, "\n") : 0;
pos = padding;
while ((pos--) > 0) strcat_s(format, SizeFormat, " ");
if (tmp == opt)
{
strcat(format, "\b");
strcat(format, cursor);
}
strcat(format, va_arg(args, char*));
}
/*if(tmp!=childs)
{
fprintf(stderr,"%s: recieved NULL pointer argument,"
" child not named", __func__);
return -1;
}*/
Sleep(delay);
system("cls");
fputs(format, stdout);
va_end(args);
} while ((chr = _getch()) != 0x0D);
return opt;
}
,它工作正常,但似乎我不能多次调用函数“ menu”(情况1 :),因为我试图循环它,但它坏了,换句话说,变得无法使用,我不能使用光标。(已对代码进行编辑以简化操作)
我是不是在做一些愚蠢和错误的事情?
还是不可能循环?如果不是这样?
预先感谢
编辑:
我发现使用调试器if (tmp != 0)chr = _getch();
在循环的第一次迭代之后单击箭头键时,不会给出正确的输入值。
为什么?
答案 0 :(得分:0)
这是我看到的简化形式:
int main()
{
int exit;
do {
exit = 1;
int response = menu(...);
switch (response)
{
case 1:
case 2:
break;
default:
exit = 0;
}
} while (!exit);
return 0;
}
只要menu()
返回1
或2
,exit == 1
因此就是(!exit) == 0
。这样可以缩短do...while
循环。
我会推荐
exit = 0; // exit is meaningful, this means "exit - false"
...
default:
exit = 1; // "exit - true"
...
while (!exit); // while not exiting, loop
或
keep_looping = 1; // you keep the original value '1' but the variable
// name is meaningful; i.e. "keep_looping - true"
...
default:
keep_looping = 0; // "keep_looping - false"
...
while (keep_looping); // "keep looping while keep_looping"
答案 1 :(得分:0)
我在循环之前添加了_getch();
,现在一切都还好,为什么?我不太清楚,但是我知道这段代码有效(我在返回_getch();
的值之前放了menu(...);
):
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <windows.h>
// LXSoft
// mod: cui/menu_021
// stdarg.h -> used for variable list of arguments (va_list, va_start ...)
// windows.h -> used for Sleep function, for *nix use unistd.h
typedef unsigned short int usint_t;
// Menu function prototype
int menu(char* name, char* prefix, char* cursor, usint_t orientation,
usint_t padding, usint_t start_pos, usint_t delay,
usint_t num_childs, ...);
int main()
{
int exit;
do {
exit = 1;
int response = menu("List des commandes", "-", "-->", 1, 3, 1, 0, 2,
"1- Ajouter un etudiant (ou un ensemble d'etudiants)",
"2- exit");
printf("\n");
switch (response)
{
case 1:
// doSomethingFoo1();
exit = 0;
break;
case 2:
//doSomethingFoo2();
exit = 1;
break;
default:
exit = 0;
}
printf("\nYour choice is: %d", response);
} while (!exit);
return 0;
}
// Menu implementation
int menu
(
char *name, // Menu name (eg.: OPTIONS)
char *prefix, // Menu prefix (eg.: [*])
char *cursor, // Menu cursor (eg.: ->)
usint_t orient, /*
* Menu orientation vertical or horzontal.
* 0 or false for horizontal
* 1 or true for vertical
*/
usint_t padding, // Menu childrens padding (eg.: 3)
usint_t start_pos, // Menu set active child (eg.: 1)
usint_t delay, // Menu children switch delay
usint_t childs, // Number of childrens
... /*
* Variable list of arguments char* type.
* Name of the childrens.
*/
)
{
va_list args;
int tmp = 0, pos;
char chr=0;
usint_t opt = start_pos;
char* format = malloc
(
(
strlen(name) + strlen(prefix) + strlen(cursor) +
3 + /* menu suffix (1 byte) and backspace (2 bytes) */
(2 * childs) + /* newline (2 bytes) times childs */
(padding*childs) + /* number of spaces times childs */
childs * 60 /* children name maxlen (15 bytes) times childs*/
) * sizeof(char)
);
do
{
if (tmp != 0)chr = _getch();
if (chr == 0x48 || chr == 0x4B)
(opt > 1 && opt != 1) ? opt-- : (opt = childs);
else if (chr == 0x50 || chr == 0x4D)
(opt >= 1 && opt != childs) ? opt++ : (opt = 1);
else {/* do nothing at this time*/ }
strcpy(format, "");
strcat(format, prefix);
strcat(format, name);
strcat(format, ":");
va_start(args, childs);
for (tmp = 1; tmp <= childs; tmp++)
{
(orient) ? strcat_s(format, SizeFormat, "\n") : 0;
pos = padding;
while ((pos--) > 0) strcat_s(format, SizeFormat, " ");
if (tmp == opt)
{
strcat(format, "\b");
strcat(format, cursor);
}
strcat(format, va_arg(args, char*));
}
/*if(tmp!=childs)
{
fprintf(stderr,"%s: recieved NULL pointer argument,"
" child not named", __func__);
return -1;
}*/
Sleep(delay);
system("cls");
fputs(format, stdout);
va_end(args);
} while ((chr = _getch()) != 0x0D);
_getch(); //THE EDIT
return opt;
}
我很想知道为什么有人知道!