2014-01-29 104 views
0

我很新的C和一般的编程,我试图执行 一个简单的命令语法分析器功能,应做到以下几点:从串行线串口命令解析

读字符并解析了字符串“boot \ n”。 如果我收到此命令,我想通过串行线输出应用程序的名称。 对于“启动AppName \ n”命令,我将使用AppName中给出的名称启动应用程序。 我该如何使用简单的解析器实现这一点,简单来说,我的意思是代码复杂性?

static void parse_input(void) 
{ 
    uint16_t i; 
    char input_buf[30]; 
    char c; 

    read_character(&c); 
    if (c == '\n') /* sync character */ 
     for (i=0; i < 20; i++) 
     { 
      read_character(&c); 
      input_buf[i] = c; 
     } 
    /* check for string "boot" in input buffer */ 
    /* maybe string compare? */ 
} 

THX

+0

这让很多的风险和不必要的假设。想想看,如果你得到多个换行符,甚至是多个boot \ n消息,或者一个boot \ n后面跟着一些其他的可能会被你的缓冲区卡住一半和一半的东西,它将会失败。 –

回答

2

假设你有一个固定大小输入缓冲区的工作,我只是满足于这样的:

fflush(stdout); 
if ((fgets(input_buf, 30, stdin)) == NULL) 
{ 
    puts("No input..."); 
    return; 
} 
if ((strncmp(buffer, "boot", 4)) != 0) 
{//boot was NOT found 
    printf("Command: %s is unknown\n", buffer); 
    return; 
} 
//boot was found, so something like: 
char *token = strtok(buffer, " \n"); 
while(token != NULL) 
{ 
    token = strtok(NULL, " \n"); 
    if (token) printf("To boot -> %s\n", token); 
} 

后者只是简单“分块”使用空格的字符串作为分隔符。因此令牌在第一次调用后将指向boot,然后指向后续的任何单词(如果有的话)。

当然,一个更简单的方法是做

char *boot_what = buffer+5; 
buffer[4] = '\0'; 

但这意味着缓冲区的前5个字符确实'b''o''o''t'' ',获得最简单的方法是这样做的:

char *boot_ptr = strstr(buffer, "boot "); 

因为strstr返回一个指针,指向在给定字符串中找到字符串的位置......好吧,玩弄<string.h>中的函数并找出最适合您的purpouse的函数。

+0

Thx求救!你的代码很简单,不会使用很多if和switch语句! – arge

1

我认为如下最好的办法是使用状态机:

  • 以可变state最初等于0一个整数,表示没有发现字符。

  • 这个变量将是条件的switch声明

  • 对于情况0:保持扫描字符,直到你找到'b',在那里你会更新state1

  • 对于情况1,同样,您将搜索'o',如果遇到任何其他字符,请将state重置为0

  • 同样,对于'o''t'

  • "boot"后,无论下面将是你的程序的名字。

1

的另一种方式获得的串行数据和分析如下我修改了代码

static void parse_input(void) 
{ 
    uint16_t i; 
    char input_buf[30]; 
    char c; 
    char cmdBuf[ 1024 ]; /* character input buffer */ 

    int bufPos = 0; 

    memset(cmdBuf,0, 1024); 
    for(;;) 
    { 
     read_character(&c); 
     if((c == '\r') || (c == '\n')) 
     { 
      if((1 + bufPos) < 1024) { 
       cmdBuf[bufPos++] = '\0'; 
      } 

      if(cmdBuf[0] != 0) 
      { 
       //serial data available in cmdBuf 
       //here your code what to do 
       //whether you application or other stuff 

      } 

      break; 
     } 
     else 
     { 
      if(c == '\b') 
      { 
       if(bufPos > 0) { 
        bufPos--; 
       } 
      } 
      else 
      { 
       if((1 + bufPos) < 1024) { 
        cmdBuf[bufPos++] = c; 
       } 
      } 
     } 
    } 

} 
+0

呃,为什么忙碌的循环? 'c'在哪里得到它的价值?为什么'strcpy'?为什么'cmdBuf [0]!= 0'不可能('cmdBuff [1024] =“”;'< - )?为什么在一个if分支的末尾有'break',并且仍然为'else'打扰?我很抱歉,但我没有看到你在这里试图做什么 –

+0

刚刚编辑的代码....找到从哪里获得的价值c.Also'如果'进程在最终缓冲区(当用户点击输入然后它执行并中断繁忙的循环),'else'用于存储'cmdBuff'中的字符,直到用户敲入enter.Also'strcpy'只用于复制它不需要我在代码中注释它。并且'cmdBuf [0]!= 0'条件用于用户在输入任何输入时按下输入。可以澄清你。 –

+0

我有点想从关闭中得到什么,但是你的'else'分支没有调用'get_character',所以它会继续向缓冲区添加相同的字符。如果'strcpy'调用是可选的,请不要将它包含在你的示例代码中,因为它所做的只是增加了开销,而关于'cmdBuff [0]'检查的全部内容仅仅是这样的:你只需要做它只有一次,而不是n次...... while(c = getchar())'循环会使你的代码更容易阅读,维护和通常用它作为起点。 –