代码之家  ›  专栏  ›  技术社区  ›  Avinash

在C中标记字符串

c
  •  2
  • Avinash  · 技术社区  · 14 年前

    下面是字符串。

    {作业已开始}{作业正在运行}{作业正在运行}{作业已完成}

    我想对{和}进行标记化,这样就可以得到“Job Started”、“Job Running”和“Job Finished”

    {Job Started}{Job\{ID1\}Running}{Job\{ID2\}Running}{Job Finished}

    我有一个指针airthmatic的解决方案,但希望避免在输入字符串上重复多次。

    任何建议。

    9 回复  |  直到 14 年前
        1
  •  5
  •   Ferruccio    14 年前

    您可以使用一个简单的有限状态机:

    #include <stdio.h>
    
    int main() {
        char *src = "{Job Started}{Job \\{ID1\\} Running}{Job \\{ID2\\} Running}{Job Finished}";
    
        char token[100] = {}, *dst = token, ch;
    
        int state = 0;
        while ((ch = *src++) != 0) {
            switch (state) {
                case 0:
                    if (ch == '{') state = 1;
                    break;
                case 1:
                    switch (ch) {
                        case '}':
                            printf("token: %s\n", token);
                            dst = token;
                            *dst = 0;
                            state = 0;
                            break;
                        case '\\':
                            state = 2;
                            break;
                        default:
                            *dst++ = ch;
                            *dst = 0;
                    }
                    break;
                case 2:
                    *dst++ = ch;
                    *dst = 0;
                    state = 1;
                    break;
            }
        }
    }
    
        2
  •  1
  •   Michael F    14 年前

    你可以用 strtok () {} (还有你需要的任何东西)。解析字符串中由两个或多个连续分隔符字符组成的序列被视为单个分隔符,此外,您还可以在连续调用之间修改分隔符集。还要注意strtok()修改了给定给它的字符串。

    编辑:我意识到这还不足以满足你的第二个要求。

        3
  •  1
  •   tenfour    14 年前

    编写自己的函数来标记这一点应该非常简单,特别是如果您知道字符串的来源(例如,不需要担心奇怪的用户输入) {a}{ , {{{{{ }a{ {blah} {blah} ).

    int tokenize(char* inp, char** outp)
    {
        char i = inp;
        int currentToken = 0;
    
        if(*i == 0)
            return 0;
    
        outp = (char**)malloc(sizeof(char*) * (strlen(inp) / 2));// allocate a buffer that can hold the maximum # of tokens.
        outp[0] = i;
    
        while(*i != 0)
        {
            switch(*i)
            {
                case '{':
                    // start a new token
                    tokenCount = tokenCount + 1;
                    outp[currentToken] = i;
                    break;
                case '}':
                    // skip this character. we assume there is a { coming next.
                    break;
                case '\\':
                    i = i + 1;
                    if(*1 == 0)
                        break;
                    // intentional fall-through
                default:
                    *outp[currentToken] = *i;
                    break;
            }
            if(*i == 0)
                break;
            i = i + 1;
        }
    
        return currentToken + 1;
    }
    
        4
  •  0
  •   thevilledev    14 年前

    我用过 strtok() 为了这个。这对带有转义字符的字符串不起作用,但我认为可以修改它来理解它们。但也不是那么简单。希望这能给你一些帮助。

    #include <stdio.h>
    #include <string.h>
    int main(void) {
        char str[] = "{Job Started}{Job Running}{Job Running}{Job Finished}";
        char* pch;
        pch = strtok(str,"{}");
        while(pch!=NULL) {
            printf("%s\n",pch);
            pch = strtok(NULL,"{}");
        }
        return 0;
    }
    

    德南说得有道理。在C语言中,字符串操作太难了,而且很容易在指针处理中失败。如果你的项目不是强制使用C语言,那么你肯定应该使用其他语言。

        5
  •  0
  •   Lombo    14 年前

    Eric Robert's scannerADT setDelimiter 方法。

    Here 是.c和.h。

        6
  •  0
  •   jim mcnamara    14 年前
    char **
    split( char **result, char *tmp, const char *src, const char *delim, size_t len)
    {
       int i=0;
       char *p=NULL;
       for(i=0; i<len; i++) 
          result[i]=NULL;
       if(!*src)
          return result;
       strcpy(tmp, src);
       for(i=0, p=strtok(tmp, delim); p!=NULL; p=strtok(NULL, delim), i++ )
       {
          result[i]=p;
       }
       return result;
    }
    

        7
  •  0
  •   Wladimir    14 年前
    char *tokenizer(char *ptr) {
        char *str = ptr;
        char *aux = ptr;
    
        while (*ptr) {
            if ( *ptr == '\\' && ( *(ptr + 1) == '{' || *(ptr + 1) == '}') ) {
                *aux++ = *(ptr + 1);
                ptr += 2;
            }
            else if ( *ptr == '{') {
                ++ptr;
            }
            else if ( *ptr == '}' ) {
                *aux++ = ( *(++ptr)  != '\0' ) ? ',' : '.';
            }
            else {
                *aux++ = *ptr++;
            }
        }
        *aux = '\0';
        return str;
    }
    
        8
  •  0
  •   Praveen S    14 年前

    你可以用 sscanf . 您可能需要使用链接中的引用创建适当的分隔符。

    /*sscanf示例*/

    #include <stdio.h>
    
    int main ()
    {
      char sentence []="Rudolph is 12 years old";
      char str [20];
      int i;
    
      sscanf (sentence,"%s %*s %d",str,&i);
      printf ("%s -> %d\n",str,i);
    
      return 0;
    }
    

    Rudolph -> 12
    

    Strtok strtok_r (strtok的可重入版本)也可以用来解析字符串。

    附言:我从另一个有类似要求的问题复制我的例子

        9
  •  0
  •   Remo.D    14 年前

    如果这是您唯一的扫描/标记化问题,那么您可能最好使用您已有的解决方案,或者按照Ferruccio的建议实现FSM。

    另一方面,如果您有其他类似的问题,您可以寻找一个工具或库来帮助您。有人建议使用lex,但您也可以设置正则表达式库。

    pmx_t ret;
    
    ret = pmxMatchStr(src,"&e\\&K{(<*!}>)}&K{(<*!}>)}&K{(<*!}>)}&L")));
    if (ret) {
      printf("%.*s, %.*s, %.*s\n",pmxLen(ret,1),pmxStart(ret,1),
                                  pmxLen(ret,2),pmxStart(ret,2),
                                  pmxLen(ret,3),pmxStart(ret,3)
    }
    

    (也可处理 {...} 吃掉了这条线的末端)

    library (pmx) 但同样的概念也适用于使用google在C中查找regexp或正则表达式库的许多其他库中的一个。