建议从特定格式解析值

时间:2015-06-25 06:04:39

标签: c

我正在研究客户端 - 服务器程序,其中初始步骤涉及在服务器端解析来自客户端的请求。输入看起来像这样。 INSERT A-> B B-> C; QUERY A B;重启; 所以有三种不同的命令,它们由';'分隔。 RESET选项没有参数。 INSERT可以包含任意数量的参数(空格分隔,每个值用&#34分隔; - >")。 QUERY再次空间分隔。服务器必须根据输入构建非循环图。所以我的问题是将此字符串解析为后续请求。我计划使用' strtok'当达到最终值时(例如' A'),创建一个INSERTS的链接列表(因为请求的数量是未知的)。但是我的代码太大了,我正在为这个问题寻找更简洁的解决方案。

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

typedef struct insert {
    char event1;
    char event2;
    struct insert * next;
}insert,*insPtr;

typedef struct query {
    char event1;
    char event2;
    struct query * next;
}query,*queryPtr;

typedef struct reset {
     int status;
 }reset,*rPtr;

 void create_node(char *events) {
     char event[2];
     char *a,*str;
     char *pch = strtok(events,"->");
     while(pch != NULL) {
         printf("%s\n",pch);
         pch = strtok(NULL,"->");
     }
}

int insert_parser(char *string) {

char *a, *b;
a =  string;
b = "INSERT ";
while(*a == *b){
    a++;
    b++;
} 

char *pch = strtok(a," ");
while(pch){
    printf("%s\n",pch);
    pch = strtok(NULL," ");
}
return(0);
}

int parse_for_values (char* command) {
    int value;
    if (strstr(command, "INSERT") !=NULL ) {
        printf("%s\n",command);
        printf ("Insert command found\n");
        value = 1;
    } else if(strstr(command, "QUERY") !=NULL) {
        printf("%s\n",command);
        printf ("Query command found\n");
        value = 2;
    } else if(strstr(command, "RESET") != NULL) {
        printf ("Reset command found\n");
        printf("%s\n",command);
        value = 3;
    } else {
        printf("unknown command:%s:\n",command);
        printf("Unknown command\n");
        return(1);
    }
    switch(value) {
        case 1:
            insert_parser(command);         
            break;
        case 2:
            break;
        case 3:
            break;

    }
    return(0);
}

int parse_for_command(char *input) {
    char *ptr;
    input = strtok(input,"\n");// this strtok is to remove the trailing '\n' in the string
    ptr = strtok(input,";");
   //   printf("%s\n",ptr); 
    char *cmdPtr;
    while(ptr != NULL) {
        cmdPtr = ptr;
        parse_for_values(cmdPtr);
//      printf("%s",ptr);
        ptr = strtok(NULL, ";"); //NULL as first argument tells strtok to work on internally held value
    }
    return(0);
}


int main() {
    char input[100];
    printf("Enter the input\n");
    fgets(input, 100, stdin);
    //printf("%s",input); 
    char *inp = input;
    inp = strtok(inp,"\n");
    create_node(inp);
    //parser(input,"INSERT ", "->");            
    //parse_for_command(input);
    return(0);
}

2 个答案:

答案 0 :(得分:2)

您必须找到单个令牌(lexical analysis)并分析此令牌序列(syntactic analysis)。您可以手动编写这些过程,也可以正式指定语言的语法,并使用现有工具自动创建所需的C代码(请参阅flexbison)。

答案 1 :(得分:0)

我并不是100%清楚你在问什么,但是输入命令与单个字符串的分离可以通过一组strtok调用来完成。此外,在调用fgets之后立即删除由fgets调用产生的尾随换行符的时间,因此您不会在字符串末尾挂起悬挂的换行符。 (例如):

fgets(input, 100, stdin);
len = strlen (input);                     /* get length of str        */
if (input[len - 1] != '\n')               /* no '\n', input too long  */
    input[--len] = 0;                     /* null-terminate           */

使用strtok分隔字符串可以使用for循环来处理单个调用中对NULL的初始和后续调用。出于示例的目的,我只使用静态声明的字符数组来保存分隔的字符串,但您也可以将p传递给您想要的任何类型列表或抽象。如果您的目的是进一步分离每个命令的各个组件,那么一个简单的while循环将指针(或两个)向下移动分离的INSERTQUERY命令将起作用。以下是示例,如果您的意图不同,请告诉我。

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

#define NCMD 10
#define LCMD 64

int main (void) {

    char input[] = "INSERT A->B B->C; QUERY A B; RESET;";
    char command[NCMD][LCMD] = {{0}};
    char *p = NULL;
    size_t i = 0;
    size_t ncmd = 0;

    for (p = strtok (input, ";"); p; p = strtok (NULL, ";")) {
        while (*p == ' ') p++;
        strncpy (command[ncmd++], p, LCMD);
    }

    printf ("\n The separated commands are:\n\n");
    for (i = 0; i < ncmd; i++)
        printf ("   command[%zu] : %s\n", i, command[i]);
    printf ("\n");

    return 0;
}

<强>输出

$ ./bin/parseinput

 The separated commands are:

   command[0] : INSERT A->B B->C
   command[1] : QUERY A B
   command[2] : RESET

注意:出于示例的目的,故意省略p上的长度验证以及对ncmd的限制检查。