将命令行语句解析为标记列表

时间:2014-02-20 02:08:45

标签: c string parsing strtok

#include <stdio.h>
#include <string.h> /* needed for strtok */
#include <unistd.h>
#include <stdlib.h>

int main(int argc, char **argv) {
        char text[10000];
    fgets(text, sizeof(text), stdin);
    char *t;
    int i;

    t = strtok(text, "\"\'| ");
    for (i=0; t != NULL; i++) {
        printf("token %d is \"%s\"\n", i, t);
        t = strtok(NULL, "\"\'| ");
    }
}

这是我试图让它分开令牌的代码的一部分

假设输入为'abc' "de f'g" hij| k "lm | no"

输出应为

token 1: "abc"
token 2: "de f'g"
token 3: "hij"
token 4: "|"
token 5: "k"
token 6: "lm | no"

我得到了一些与众不同的东西,但无论如何我可以将它更改为这种格式?

2 个答案:

答案 0 :(得分:0)

你要做的事实上是一个解析器。 strtok不是一个非常好的工具,你可以更好地写自己的运气。 strtok的假设是,无论是否划分您的令牌都是不重要的,因此可以用'\0'覆盖。但是你要关心分隔符是什么。

您唯一的问题是|语法。您希望将其用作令牌分隔符令牌的事实可能会使您的代码更复杂(但不会太多)。在这里,您遇到hij紧跟|的问题。如果您终止hij以获取令牌,则必须覆盖|。您必须存储已覆盖的字符并将其还原,或将字符串复制到其他位置。

你基本上有三种情况:

  • |是一个特殊的分隔符,也是一个标记;
  • 引用分隔符"'匹配所有内容,直到相同类型的下一个引号;
  • 否则,令牌由空格分隔。

答案 1 :(得分:0)

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

char *getToken(char **sp){
    static const char *sep = " \t\n";
    static char vb[] = "|", vbf;
    char *p, *s;
    if(vbf){
        vbf = 0;
        return vb;
    }
    if (sp == NULL || *sp == NULL || **sp == '\0') return(NULL);
    s = *sp;
    if(*s == '"')
        p = strchr(++s, '"');
    else if(*s == '\'')
        p = strchr(++s, '\'');
    else
        p = s + strcspn(s, "| \t\n");
    if(*p != '\0'){
        if(*p == '|'){
            *vb = vbf = '|';
        }
        *p++ = '\0';
        p += strspn(p, sep);
    }
    *sp = p;
    if(!*s){
        vbf = 0;
        return vb;
    }
    return s;
}

int main(int argc, char **argv) {
    char text[10000];
    fgets(text, sizeof(text), stdin);
    char *t, *p = text;
    int i;

    t = getToken(&p);
    for (i=1; t != NULL; i++) {
        printf("token %d is \"%s\"\n", i, t);
        t = getToken(&p);
    }
    return 0;
}