我正在研究客户端 - 服务器程序,其中初始步骤涉及在服务器端解析来自客户端的请求。输入看起来像这样。 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);
}
答案 0 :(得分:2)
您必须找到单个令牌(lexical analysis)并分析此令牌序列(syntactic analysis)。您可以手动编写这些过程,也可以正式指定语言的语法,并使用现有工具自动创建所需的C代码(请参阅flex和bison)。
答案 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循环将指针(或两个)向下移动分离的INSERT
或QUERY
命令将起作用。以下是示例,如果您的意图不同,请告诉我。
#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
的限制检查。