命令行界面(CLI):您的建议 [英] Command Line Interface (CLI): your recommendations

查看:47
本文介绍了命令行界面(CLI):您的建议的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

你好,全部!


我正在实施简单的CLI(平面模型,没有树式菜单等)。命令

行看起来像这样:< command> <参数1> < param2的> ...< paramN> (其中

N = 1..4)

想法非常简单:


1)得到整串输入line

2)预设的字符串匹配表< command>

3)预设的函数调用表

4)scan< command>用于字符串的表,如果匹配 - 调用匹配函数(I

将所有回调函数声明为具有相同的格式)


这是执行此算法的一部分的代码。我遇到的问题

如果连续按下''Enter'',那么有时输出PROMPT turnes

笨拙,即它在一行中重复打印。


在我走得太远之前,我想问一下你对概念的看法我是

使用和建议如果可能的话:


#define _GNU_SOURCE


#include< stdio.h>

#include< string.h>

#include< stdlib.h>

#include< unistd.h>


#define COUNT(a)(sizeof(a )/ sizeof(a [0]))

const char * PROMPT =" CLI>" ;;


enum errCodes {RC_SUCCESS = 0,RC_ERROR = -1};


/ * table of< commands> * /

const char * commands [] = {

" show",

" version",

" help",

" port",

" exit"

};


/ *回调函数* /

typedef int(* handler_ptr_t)(int,char **);


/ * define命令行: <命令> <参数1> < param2的> ...< paramN> * /

typedef struct cmdLineEntry_s {

#define MAX_NAME 20

char命令[MAX_NAME];

#define MAX_ARGS 4

char params [MAX_ARGS];

unsigned int params_num;

handler_ptr_t cmd_handler;

} cmdLineEntry_t;


int cliShow(int argc,char * argv [])

{

puts(" cliShow()stub" );

返回0;

}


int cliVersion(int argc,char * argv [])

{

puts(" cliVersion()stub);

返回0;

}


int cliHelp(int argc,char * argv [])

{

puts(" cliHelp()stub");

返回0;

}


int cliPort(int argc,char * argv [])

{

put(" cliPort()stub");

返回0;

}


int cliExit(int argc,char * argv [])

{

puts(" cliExit()stub);

exit( EXI T_SUCCESS);

}


/ *定义表函数指针* /

handler_ptr_t ftable [] = {cliShow,cliVersion, cliHelp,cliPort,cliExit};


/ *解析命令行和填充结构* /

static int

cliParseCommandLine(char * buf,cmdLineEntry_t * cli)

{

const char delim [] =" \ t \ n" ;;

unsigned int i;

char * token;


memset(cli,0, sizeof * cli);


token = strtok(buf,delim);

for(i = 0; i< COUNT(commands); i ++) {

if(!strcmp(token,commands [i])){

strcpy(cli->; command,token);

cli-> cmd_handler = ftable [i];

i = 0;

for(token = strtok(NULL,delim); token!= NULL;){

cli-> params [i ++] = token;

token = strtok(NULL,delim);

}

cli-> params_num = i;

返回0;

}

}

返回-1;

}


int main(无效)

{

char buf [BUFSIZ] = { 0};

cmdLineEntry_t cli = {{0},{NULL},0,NULL};


while(1){

printf("%s",PROMPT);

if(fgets(buf,BUFSIZ,stdin)){

/ * skip LF / CR / TAB / SP * /

if(buf [0] ==''\ n''|| buf [0] ==' || BUF [0] == \r || buf [0]

==''\ t'')

继续;


/ *解析流* /

if(cliParseCommandLine(buf,& cli)< 0){

printf(" Error:invalid command!\ n");

继续;

}

else {

cli.cmd_handler(cli.params_num,cli.params);

}

}

else继续; / * EOL * /

} / *而* /


返回0;

}

TIA!

最诚挚的问候,罗马马沙克。电子邮件: mr*@tusur.ru

Hello, All!

I''m implementing simple CLI (flat model, no tree-style menu etc.). Command
line looks like this: <command> <param1> <param2> ... <paramN> (where
N=1..4)
And idea is pretty simple:

1) get whole string of input line
2) preset table of strings matching <command>
3) preset table of function calls
4) scan <command> table for string, if match - call matching function (I
declare ALL callback functions as having the same format)

Here is code implementing part of this algorithm. The problem I came across
is if pressing ''Enter'' continuously then sometimes output of PROMPT turnes
out clumsy, i.e. it''s printed repeatedly in a line.

Before I went too far, I would like to ask your opinion about concept I''m
using and recommendations if possible:

#define _GNU_SOURCE

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

#define COUNT(a) (sizeof(a) / sizeof(a[0]))

const char *PROMPT = "CLI>";

enum errCodes { RC_SUCCESS = 0, RC_ERROR = -1 };

/* table of <commands> */
const char *commands[] = {
"show",
"version",
"help",
"port",
"exit"
};

/* callback function */
typedef int (*handler_ptr_t)(int, char**);

/* define command line: <command> <param1> <param2> ... <paramN> */
typedef struct cmdLineEntry_s {
#define MAX_NAME 20
char command[MAX_NAME];
#define MAX_ARGS 4
char params[MAX_ARGS];
unsigned int params_num;
handler_ptr_t cmd_handler;
} cmdLineEntry_t;

int cliShow(int argc, char *argv[])
{
puts("cliShow() stub");
return 0;
}

int cliVersion(int argc, char *argv[])
{
puts("cliVersion() stub");
return 0;
}

int cliHelp(int argc, char *argv[])
{
puts("cliHelp() stub");
return 0;
}

int cliPort(int argc, char *argv[])
{
puts("cliPort() stub");
return 0;
}

int cliExit(int argc, char *argv[])
{
puts("cliExit() stub");
exit(EXIT_SUCCESS);
}

/* define table functions pointers */
handler_ptr_t ftable[] = { cliShow, cliVersion, cliHelp, cliPort, cliExit };

/* parse command line and fill structure */
static int
cliParseCommandLine(char *buf, cmdLineEntry_t *cli)
{
const char delim[] = " \t\n";
unsigned int i;
char *token;

memset(cli, 0, sizeof *cli);

token = strtok(buf, delim);
for (i = 0; i < COUNT(commands); i++) {
if (!strcmp(token, commands[i])) {
strcpy(cli->command, token);
cli->cmd_handler = ftable[i];
i = 0;
for (token = strtok(NULL, delim); token != NULL; ) {
cli->params[i++] = token;
token = strtok(NULL, delim);
}
cli->params_num = i;
return 0;
}
}
return -1;
}

int main(void)
{
char buf[BUFSIZ] = {0};
cmdLineEntry_t cli = { {0}, {NULL}, 0, NULL };

while (1) {
printf("%s", PROMPT);
if ( fgets(buf, BUFSIZ, stdin) ) {
/* skip LF/CR/TAB/SP */
if (buf[0] == ''\n'' || buf[0] == '' '' || buf[0] == ''\r'' || buf[0]
== ''\t'')
continue;

/* parse stream */
if ( cliParseCommandLine(buf, &cli) < 0 ) {
printf("Error : invalid command!\n");
continue;
}
else {
cli.cmd_handler(cli.params_num, cli.params);
}
}
else continue; /* EOL */
} /* while */

return 0;
}

TIA!
With best regards, Roman Mashak. E-mail: mr*@tusur.ru

推荐答案

在文章< ds ********** @ relay.tomsk.ru> ;,罗马Mashak< mr*@tusur.ru>写道:
In article <ds**********@relay.tomsk.ru>, Roman Mashak <mr*@tusur.ru> wrote:
我正在实现简单的CLI
这是实现此算法的一部分的代码。我遇到的问题是,如果连续按下''Enter'',那么PROMPT turnes的输出有时会笨拙,即它会反复打印成一行。
const char * PROMPT =" CLI>" ;;
int main(void)
{char buf [BUFSIZ] = {0};
cmdLineEntry_t cli = {{0},{NULL},0,NULL};

while(1){
printf("%s",PROMPT);


在你的PROMPT中有\ n,并且你没有fflush()

输出,所以你的提示不一定出现在任何

相对于输入的特定位置。它可能不会出现在

all,直到你出于其他原因输出\ n。


if(fgets(buf,BUFSIZ,stdin)) {
/ *跳过LF / CR / TAB / SP * /
如果(buf [0] ==''\ n''|| buf [0] ==''''|| buf [0] ==''\'''|| buf [0]
==''\t'')
继续;
I''m implementing simple CLI Here is code implementing part of this algorithm. The problem I came across
is if pressing ''Enter'' continuously then sometimes output of PROMPT turnes
out clumsy, i.e. it''s printed repeatedly in a line. const char *PROMPT = "CLI>"; int main(void)
{
char buf[BUFSIZ] = {0};
cmdLineEntry_t cli = { {0}, {NULL}, 0, NULL };

while (1) {
printf("%s", PROMPT);
There is in \n in your PROMPT, and you do not fflush()
the output, so your prompt is not certain to appear at any
particular place relative to the input. It might not appear at
all until you happen to output a \n for other reasons.

if ( fgets(buf, BUFSIZ, stdin) ) {
/* skip LF/CR/TAB/SP */
if (buf[0] == ''\n'' || buf[0] == '' '' || buf[0] == ''\r'' || buf[0]
== ''\t'')
continue;



继续是相对于while(),并且在空行的情况下你不打印

。因此,如果你的缓冲区中有\\ b $ ba系列的\ n,你最终会重复

printf("%s",PROMPT),因为没有在那个,几个

提示将全部出现在一行。

-

好​​的,只有流行语。两个音节,上衣。 - Laurie Anderson



That continue is relative to the while(), and you do not print
anything out in the case of the empty line. Thus if you have
a series of \n in your buffer, you will end up doing repeated
printf("%s", PROMPT) and since there is no \n in that, the several
prompts will all come out on one line.
--
Okay, buzzwords only. Two syllables, tops. -- Laurie Anderson




" Roman Mashak" < mr*@tusur.ru>在消息中写道

news:ds ********** @ relay.tomsk.ru ...

"Roman Mashak" <mr*@tusur.ru> wrote in message
news:ds**********@relay.tomsk.ru...
大家好!
<我正在实现简单的CLI(平面模型,没有树形菜单等)。命令
行看起来像这样:< command> <参数1> < param2的> ...< paramN> (其中N = 1..4)
想法非常简单:


这个编译干净吗?如果我gcc-Wall,我得到两个错误。


第一个错误在于:for(token = strtok(NULL,delim); token!= NULL;){
cli-> params [i ++] = token;
token = strtok(NULL,delim);


我认为中间线应该是:

cli-> params [i ++] = * token;


第二个错误在这里:else {
cli.cmd_handler(cli.params_num,cli.params);
Hello, All!

I''m implementing simple CLI (flat model, no tree-style menu etc.). Command
line looks like this: <command> <param1> <param2> ... <paramN> (where
N=1..4)
And idea is pretty simple:
Does this compile cleanly for you? If I gcc -Wall, I get two errors.

The first error is here: for (token = strtok(NULL, delim); token != NULL; ) {
cli->params[i++] = token;
token = strtok(NULL, delim);
I think the middle line should be:
cli->params[i++] = *token;

The second error is here: else {
cli.cmd_handler(cli.params_num, cli.params);




cli.params是一个数组char,但handler_pointer_t函数接受一个指向char数组的'/ b $ b指针''char * argv []'',作为第二个参数。

Rod Pemberton



cli.params is an array of char, but the handler_pointer_t functions accept a
pointer to array of char, ''char *argv[]'', for the second argument.
Rod Pemberton





" Rod Pemberton" <做********* @ sorry.bitbucket.cmm>在消息中写道

news:43 ******** @ news.bea.com ...

"Rod Pemberton" <do*********@sorry.bitbucket.cmm> wrote in message
news:43********@news.bea.com...

Roman Mashak < mr*@tusur.ru>在消息中写道
新闻:ds ********** @ relay.tomsk.ru ...

"Roman Mashak" <mr*@tusur.ru> wrote in message
news:ds**********@relay.tomsk.ru...
大家好!

我''实现简单的CLI(平面模型,没有树状菜单等)。
Hello, All!

I''m implementing simple CLI (flat model, no tree-style menu etc.).



命令


经过深思熟虑,你可能想要一个setbuf()或者两个:


setbuf(stdin,NULL);

setbuf(stdout,NULL);

Rod Pemberton


Command

After thought, you might want a setbuf() or two:

setbuf(stdin,NULL);
setbuf(stdout,NULL);
Rod Pemberton


这篇关于命令行界面(CLI):您的建议的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆