在c中的分隔符之间提取文本

时间:2013-11-14 19:29:40

标签: c string

我正在寻找的内容基本上等同于在括号中提取文本,这就是我将使用的示例。如果我的输入类似(test 1 2)(test 3 4)test foo bar(test again),则下面的代码会返回我想要的内容:

token: test 1 2
token: test 3 4
token: test again

但如果我的输入是(test 1 (test 2 3)foo(bar test) again),我会得到

token: test 1 
token: test 2 3
token: bar test

我不想看到test 1。是的,这是在左边的paren和右边的paren之间,但是这意味着在这一点数据的上游出现了问题。

void print_tokens(char *s) {
    printf("input: %s\n",s);
    char *output;
    const char *valid = "abcdefghijklmnopqrstuvwxyz0123456789 ";
    unsigned int length;
    s=strchr(s,'(')+1;
    length=strspn(s,valid);
    while(s!=NULL && length>0) {
        output=malloc(length+1);
        strncpy(output,s,length);
        output[length]='\0';
        printf("token: %s\n",output);
        free(output);
        if(strchr(s,'(')!=NULL) {
            s=strchr(s,'(')+1;
            length=strspn(s,valid);
        } else {
            s=NULL;
        }
    }
}

除了内存管理相当松散之外,这个slap-dash方法可能“足够接近”,因为我有另一个函数(实际上会传递输出,它会对自己的输入进行一些检查,但这可能仍然会让一些表达不正确的表达,并且如果可能的话我想避免这种情况。虽然我正在寻找的东西可以很容易地用正则表达式来概括(我相信/.*\(([a-z0-9 ]*?)\)/),但它必须更多 - 或者更少的标准C. GNU C,Boost,以及我见过的大多数其他库,我都无法使用字符串解析或正则表达式。

有没有更好的方法来提取这个消除无关令牌的文本?并且使用有效字符集更灵活(例如,除了左右括号之外的所有)?

2 个答案:

答案 0 :(得分:0)

Crappy伪代码:

  char *c = start;
  char *d;

  while (*c) {
    while (*c && *c != '(') c++;
    /* we found a left paren */
    d = ++c;
    while (*d && *d != ')') {
      if (*d == '(') {
        /* reset! */
        c = d;
        break;
      }
      if (*d == ')') {
        *d = 0;
        printf("token: %s\n", c);
        c = d;
        continue;
      }
      d++
    }
  }
  printf("finished\n");

答案 1 :(得分:0)

这应该就是这样做的:

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

void print_tokens(char *s)
{
    printf("input: %s\n", s);
    char *start = s;
    char *end = s;
    while(*s) {
        if(*s == '(') start = s;
        else if(*s == ')') end = s;
        if(start < end && *start) {
              *end = 0;
              printf("token: %s\n", start+1);
              start = s = end;
        }
        s++;
    }
}

int main()
{
    char str[] = "(test 1 (test 2 3)foo(bar test) again)";
    char str2[] = "(test 1 2)(test 3 4)test foo bar(test again)";
    print_tokens(str);
    print_tokens(str2);
    return 0;
}

它适用于您给我的两个测试用例。请注意,它会复制原始字符串,因此如果您不希望它执行此操作,则应删除代码以复制字符串。

希望这有帮助!

亚历