在带有strtok函数的空格中的c split char *中,除非引号之间

时间:2014-10-03 21:26:32

标签: c

有没有办法用strtok函数执行此操作?或任何建议?

示例:

Insert "hello world" to dbms

结果:

Insert
"hello world"
to
dbms

6 个答案:

答案 0 :(得分:6)

strtok或标准C库中的任何其他功能都无法为您执行此操作。要获得它,你必须自己编写代码,或者你必须在一些外部库中找到一些现有的代码。

答案 1 :(得分:4)

此函数采用分隔符,openblock和closeblock字符。块中将忽略分隔符,并且结束块字符必须与开始块字符匹配。空格和块上的示例拆分由引号和括号,大括号和<>定义。感谢Jongware的评论!

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

char *strmbtok ( char *input, char *delimit, char *openblock, char *closeblock) {
    static char *token = NULL;
    char *lead = NULL;
    char *block = NULL;
    int iBlock = 0;
    int iBlockIndex = 0;

    if ( input != NULL) {
        token = input;
        lead = input;
    }
    else {
        lead = token;
        if ( *token == '\0') {
            lead = NULL;
        }
    }

    while ( *token != '\0') {
        if ( iBlock) {
            if ( closeblock[iBlockIndex] == *token) {
                iBlock = 0;
            }
            token++;
            continue;
        }
        if ( ( block = strchr ( openblock, *token)) != NULL) {
            iBlock = 1;
            iBlockIndex = block - openblock;
            token++;
            continue;
        }
        if ( strchr ( delimit, *token) != NULL) {
            *token = '\0';
            token++;
            break;
        }
        token++;
    }
    return lead;
}

int main (int argc , char *argv[]) {
    char *tok;
    char acOpen[]  = {"\"[<{"};
    char acClose[] = {"\"]>}"};
    char acStr[] = {"this contains blocks \"a [quoted block\" and a [bracketed \"block] and <other ]\" blocks>"};

    tok = strmbtok ( acStr, " ", acOpen, acClose);
    printf ( "%s\n", tok);
    while ( ( tok = strmbtok ( NULL, " ", acOpen, acClose)) != NULL) {
        printf ( "%s\n", tok);
    }

    return 0;
}

输出

包含

“a [引用区块”

一个
[括号内的“阻止”

  

答案 2 :(得分:2)

使用strtok()没有运气。

有机会使用state machine

#include <stdio.h>

void printstring(const char *frm, const char *to) {
  fputc('<', stdout);  // <...>\n Added for output clarity
  while (frm < to) {
    fputc(*frm++, stdout);
  }
  fputc('>', stdout);
  fputc('\n', stdout);
}

void split_space_not_quote(const char *s) {
  const char *start;
  int state = ' ';
  while (*s) {
    switch (state) {
      case '\n': // Could add various white-space here like \f \t \r \v
      case ' ': // Consuming spaces
        if (*s == '\"') {
          start = s;
          state = '\"';  // begin quote
        } else if (*s != ' ') {
          start = s;
          state = 'T';
        }
        break;
      case 'T': // non-quoted text
        if (*s == ' ') {
          printstring(start, s);
          state = ' ';
        } else if (*s == '\"') {
          state = '\"'; // begin quote
        }
        break;
      case '\"': // Inside a quote
        if (*s == '\"') {
          state = 'T'; // end quote
        }
        break;
    }
    s++;
  } // end while
  if (state != ' ') {
    printstring(start, s);
  }
}

int main(void) {
  split_space_not_quote("Insert \"hello world\" to dbms");
  return 0;
}

<Insert>
<"hello world">
<to>
<dbms>

答案 3 :(得分:0)

也许你可以使用正则表达式(即Regular expressions in C: examples?

以下是您可以使用的正则表达式示例:/([\w]+)|(\"[\w\ ]+\")/gi

要使用正则表达式训练自己,您还应该使用:http://regex101.com/

答案 4 :(得分:0)

您可以执行第一次传递,其中strtok使用引号字符作为分隔符来分割字符串。然后执行第二次传递,将空格字符作为未引用的结果字符串的分隔符。

编辑添加工作源代码:

bool quotStr = (*stringToSplit == '\"');
char* currQuot = strtok(stringToSplit, "\"");
char* next = NULL;

while(currQuot)
{
    if(quotStr)
    {
        printf("\"%s\"\n", currQuot);
        quotStr = false;
    }
    else
    {
        // remember where the outer loop strtok left off
        next = strtok(next, "\0");

        // subdivide
        char* currWord = strtok(currQuot, " ");
        while(currWord)
        {
            printf("%s\n", currWord);
            currWord = strtok(NULL, " ");
        }
        quotStr = true;
    }

    currQuot = strtok(next, "\"");
    next = NULL;
}

我相信在空引用字符串的情况下,这仍然会失败,但是......

答案 5 :(得分:0)

我的解决方案是strtok()。它只对以Space-Quotes开头并以Quotes-Space

结尾的单词组合
void split(char *argstring)
{
    int _argc = 0;
    char **_argv = malloc(sizeof(char*));
    char *token;
    int myFlag = 0;

    for(token = strtok(argstring, " "); token != NULL; token = strtok(NULL, " "))
    {
        if (1 == myFlag)
        {
            //One of the previous token started with double quotes
            if ('\"' == token[strlen(token)-1]) myFlag = 0; //This token ends with double quotes
            _argv[_argc-1] = realloc(_argv[_argc-1], strlen(_argv[_argc-1]) + strlen(token) + 2);   //Enlarge the previous token
            strcat(_argv[_argc-1], " ");
            strcat(_argv[_argc-1], token);
        }
        else
        {
            if ('\"' == token[0]) myFlag = 1;                       //This token starts with double quotes
            _argv = realloc(_argv, (_argc + 1) * sizeof(char*));    //Add one element to the array of strings
            _argv[_argc] = m2m_os_mem_alloc(strlen(token) + 1);     //Allocate the memory for the Nth element
            strcpy(_argv[_argc], token);                            //Copy the token in the array
            _argc++;
        }
    }

    do
    {
        m2m_os_mem_free(_argv[_argc--]);
    } while (_argc >= 0);
}