字符串解析在C。。。strtok()不';我还没完全做完

字符串解析在C。。。strtok()不';我还没完全做完,c,parsing,strtok,C,Parsing,Strtok,好的。。。第一个问题,所以请原谅我,如果它不是很容易理解的第一次去 我正试图通过几个不同的条件解析输入到stdin的字符串。 输入字符串示例:将其移动到“我需要的令牌”\n 我想将其解析为令牌,如下所示: 令牌1=move 令牌2=此 令牌3=进入 令牌4=我需要的令牌 如果在遇到引号之前标记都是空白的(非常简单),那么打开和关闭引号中的所有内容都将被视为单个标记 我尝试过几种不同的方法,但不幸的是,我觉得我可能会在这里超过我的头,所以任何帮助将不胜感激 我的最新尝试: fgets(in

好的。。。第一个问题,所以请原谅我,如果它不是很容易理解的第一次去

我正试图通过几个不同的条件解析输入到stdin的字符串。
输入字符串示例:
将其移动到“我需要的令牌”\n

我想将其解析为令牌,如下所示:

令牌1=
move

令牌2=

令牌3=
进入

令牌4=
我需要的令牌

如果在遇到引号之前标记都是空白的(非常简单),那么打开和关闭引号中的所有内容都将被视为单个标记

我尝试过几种不同的方法,但不幸的是,我觉得我可能会在这里超过我的头,所以任何帮助将不胜感激

我的最新尝试:

    fgets(input, BUFLEN, stdin); //gets the input
    input[strlen(input)-1] = '\0';//removes the new line

    printf("Input string = %s\n",input);//Just prints it out for me to see

    char *token = strtok(input,delim);//Tokenizes the input, which unfortunately does not do what I need.  delim is just my string of delimiters which currently only has a " " in it.

我试图一次扫描字符串一个字符,然后将这些字符放入数组中,这样我就可以得到我想要的字符,但失败得很惨。

自定义版本的
my\u strtok\r
的最终解决方案就在这里。此解决方案比不可重入的解决方案具有优势:
strtok

my_strtok\u r
是可重入的:您可以同时从多个线程调用它们,或者在嵌套循环中调用它们,等等

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

char * my_strtok_r(char *s, const char *delim1, const char *delim2, char **save_ptr)
{
    char *end;
    size_t s1;
    size_t s2;
    int delim2found = 0;

    if (s == NULL)
        s = *save_ptr;

    if (*s == '\0'){
        *save_ptr = s;
        return NULL;
    }

    s1 = strspn (s, delim1);
    s2 = strspn (s, delim2);

    if(s2 > s1){
        s += s2;
        delim2found  = 1;
    }
    else{
        s += s1;
    }

    if (*s == '\0'){
        *save_ptr = s;
        return NULL;
    }

    /* Find the end of the token.  */
    if(delim2found)
        end = s + strcspn (s, delim2);
    else
        end = s + strcspn (s, delim1);

    if (*end == '\0') {
        *save_ptr = end;
        return s;
    }

    /* Terminate the token and make *save_ptr point past it. */
    *end = '\0';
    *save_ptr = end + 1;
    return s;
}

int main (void)
{
    char str[] = "   123 abc \"SPLITTING  WORKS\"  yes! \"GREAT WE HAVE A SOLUTION\"  !    ";
    char *d1 = " ";
    char *d2 = "\"";
    char *token;
    char *rest = str;
    char array[20][80];

    printf ("Splitting string \"%s\" into tokens:\n",str);

    size_t nr_of_tokens = 0;
    while ((token = my_strtok_r(rest, d1, d2, &rest)))
    {
        strcpy (array[nr_of_tokens], token);
        nr_of_tokens++;
    }

    for(int i=0; i < nr_of_tokens; i++)
        printf ("%s\n",array[i]);

    return 0;
}
这是您可以使用的另一个解决方案(经过充分测试)。您可以混合使用由空格和
“\”
分隔的任意数量的标记。它可以根据您的需要进行配置。代码本身给出了详细的解释

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

char *get_str_segment(char *output_str, char *input_str, char extDel)
{
    /*
     Purpose :

        To copy to output first segment.

        To extract the segment two types of delimiters are used:
            1. white space delimiter
            2. 'extDel' -
                 do not put here white space or '\0'!
                 (typicaly '"'  = quote!)

        'extDel' allows us to put white spaces inside the segment.
        Notice that 'extDel' cannot be embedded inside the segment!
        It makes 'extDel' special character which will not be encountered
        in the 'output_string'! First appearance of 'extDel' starts new
        segment!
        Notice that unbalanced 'extDel' will cause coping whole string to
        destination from that point!

        Return:

        Pointer to the first character after the segment
        or NULL !!!

        we will not allow **empty** segments with unbalanced 'extDel'
        if ('extDel' is unbalanced) it has to have at list one character!
        It can be white space!


        Notice!
        "get_str_segment()" on strings filed with white spaces
         and empty strings will return *** NULL *** to indicate that
         no conclusive segment has been found!


        Example:
        input_str  =    "  qwerty"123 45"  "samuel" G7 "
        output_str = ""

        //  Call:  
        char *ptr = get_str_segment(output_str,input_str,'"');

        Result:

        input_str  =    "  qwerty"123 45"  "samuel" G7 "

                                 ^
                                 |
        ptr----------------------.

        output_str =    "qwerty"
    */

    char *s  = input_str;
    char *d  = output_str;
    char  i  = 0;


    if(!s) return NULL; // rule #1 our code never brakes!
    if(!d) return NULL;

    // eliminate white spaces from front of the block

    while(1)
    {
        if ( *s == '\0')
        {
            *d = '\0' ;       // end the output string
            return (NULL) ;   // return NULL to indicate that no
            // coping has been done.
            //
            //
            // "get_str_segment()" on
            // strings filed with white spaces
            // and empty strings
            // will return NULL to indicate that
            // no conclusive segment has been found
            //
        }

        if (isspace(*s)) ++s;  // move pointer to next char
        else break;            // break the loop!
    }

    // we found first non white character!

    if( *s != extDel)
    {
        // copy block up to end of string first white space or extDel

        while( ((*s) != '\0') && (!isspace(*s)) && ((*s) != extDel) )
        {
            *d = *s;        // copy segment characters
            ++s;
            ++d;
        }

        *d = '\0' ;  // end the destination string
        return (s);  // return pointer to end of the string  ||
        // trailing white space ||
        // 'extDel' char
    }
    else // It is 'extDel' character !
    {
        ++s; // skip opening 'extDel'

        while( ((*s) != '\0') && ((*s) != extDel) )
        {
            i=1;            // we executed loop at list one time

            *d = *s;        // copy segment characters till '\0' or extDel
            ++s;
            ++d;
        }

        *d = '\0' ;  // end the destination string

        if( *s == extDel ) ++s;  // skip *closing* 'extDel'
        else
        {
            // unbalanced 'extDel'!
            printf("WARNING:get_str_segment: unbalanced '%c' encountered!\n",extDel);

            if (i==0) return NULL;  // we will not allow
            // **empty** unbalanced segments 'extDel'

            // if ('extDel' is unbalanced) it has to have at list one character!
            // It can be white space!
        }

        return (s);  // return pointer to next char after 'extDel'
        // ( It can be '\0')
        // if it is '\0' next pass will return 'NULL'!

    }
}

int parse_line_to_table(int firstDim, int secondDim, char *table, char * line, char separator)
{
    // Purpose:
    // Parse 'line' to 'table'
    // Function returns: number of segments
    // 'table' has to be passed from outside

    char* p;
    int   i;

    if(!table) return (-1);

    // parse segments to 'table':
    if(line)
    {
        p = line; // A necessary initialization!

        for(i=0; i<firstDim; i++)
        {
            p = get_str_segment( table+i*secondDim , p , separator );
            if(p==NULL) break;
        }
    }
    else
        return (-1);

    // debug only
    //    for(int j=0; j<i; j++) { printf(" i=%d %s",j, table+j*secondDim ); }
    //    printf("\n");

    return (i); // notice that i is post incremented
}

int main(void)
{
    char table[20][80];
    char *line =   "move this into \"tokens that I need\"";

    int ret = parse_line_to_table(20, 80, table, line, '\"');

    for(int i = 0; i < ret; i++ )
        printf("%s\n",table[i]);

    return 0;
}

什么是
delim
?delim是我的分隔字符字符串…目前只有“我把它添加到我的问题中谢谢你的帮助!有没有可能将这些令牌存储在阵列中,以便以后访问?@Mike我想现在你已经拥有了所有需要的东西。第一个例子已经完全修改过了。它很小,而且效果很好!再次感谢你的帮助!我将深入研究你写的东西,看看我是否能更好地理解它。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include <ctype.h>

char *get_str_segment(char *output_str, char *input_str, char extDel)
{
    /*
     Purpose :

        To copy to output first segment.

        To extract the segment two types of delimiters are used:
            1. white space delimiter
            2. 'extDel' -
                 do not put here white space or '\0'!
                 (typicaly '"'  = quote!)

        'extDel' allows us to put white spaces inside the segment.
        Notice that 'extDel' cannot be embedded inside the segment!
        It makes 'extDel' special character which will not be encountered
        in the 'output_string'! First appearance of 'extDel' starts new
        segment!
        Notice that unbalanced 'extDel' will cause coping whole string to
        destination from that point!

        Return:

        Pointer to the first character after the segment
        or NULL !!!

        we will not allow **empty** segments with unbalanced 'extDel'
        if ('extDel' is unbalanced) it has to have at list one character!
        It can be white space!


        Notice!
        "get_str_segment()" on strings filed with white spaces
         and empty strings will return *** NULL *** to indicate that
         no conclusive segment has been found!


        Example:
        input_str  =    "  qwerty"123 45"  "samuel" G7 "
        output_str = ""

        //  Call:  
        char *ptr = get_str_segment(output_str,input_str,'"');

        Result:

        input_str  =    "  qwerty"123 45"  "samuel" G7 "

                                 ^
                                 |
        ptr----------------------.

        output_str =    "qwerty"
    */

    char *s  = input_str;
    char *d  = output_str;
    char  i  = 0;


    if(!s) return NULL; // rule #1 our code never brakes!
    if(!d) return NULL;

    // eliminate white spaces from front of the block

    while(1)
    {
        if ( *s == '\0')
        {
            *d = '\0' ;       // end the output string
            return (NULL) ;   // return NULL to indicate that no
            // coping has been done.
            //
            //
            // "get_str_segment()" on
            // strings filed with white spaces
            // and empty strings
            // will return NULL to indicate that
            // no conclusive segment has been found
            //
        }

        if (isspace(*s)) ++s;  // move pointer to next char
        else break;            // break the loop!
    }

    // we found first non white character!

    if( *s != extDel)
    {
        // copy block up to end of string first white space or extDel

        while( ((*s) != '\0') && (!isspace(*s)) && ((*s) != extDel) )
        {
            *d = *s;        // copy segment characters
            ++s;
            ++d;
        }

        *d = '\0' ;  // end the destination string
        return (s);  // return pointer to end of the string  ||
        // trailing white space ||
        // 'extDel' char
    }
    else // It is 'extDel' character !
    {
        ++s; // skip opening 'extDel'

        while( ((*s) != '\0') && ((*s) != extDel) )
        {
            i=1;            // we executed loop at list one time

            *d = *s;        // copy segment characters till '\0' or extDel
            ++s;
            ++d;
        }

        *d = '\0' ;  // end the destination string

        if( *s == extDel ) ++s;  // skip *closing* 'extDel'
        else
        {
            // unbalanced 'extDel'!
            printf("WARNING:get_str_segment: unbalanced '%c' encountered!\n",extDel);

            if (i==0) return NULL;  // we will not allow
            // **empty** unbalanced segments 'extDel'

            // if ('extDel' is unbalanced) it has to have at list one character!
            // It can be white space!
        }

        return (s);  // return pointer to next char after 'extDel'
        // ( It can be '\0')
        // if it is '\0' next pass will return 'NULL'!

    }
}

int parse_line_to_table(int firstDim, int secondDim, char *table, char * line, char separator)
{
    // Purpose:
    // Parse 'line' to 'table'
    // Function returns: number of segments
    // 'table' has to be passed from outside

    char* p;
    int   i;

    if(!table) return (-1);

    // parse segments to 'table':
    if(line)
    {
        p = line; // A necessary initialization!

        for(i=0; i<firstDim; i++)
        {
            p = get_str_segment( table+i*secondDim , p , separator );
            if(p==NULL) break;
        }
    }
    else
        return (-1);

    // debug only
    //    for(int j=0; j<i; j++) { printf(" i=%d %s",j, table+j*secondDim ); }
    //    printf("\n");

    return (i); // notice that i is post incremented
}

int main(void)
{
    char table[20][80];
    char *line =   "move this into \"tokens that I need\"";

    int ret = parse_line_to_table(20, 80, table, line, '\"');

    for(int i = 0; i < ret; i++ )
        printf("%s\n",table[i]);

    return 0;
}
move                                                                                                                                                                                                                                             
this                                                                                                                                                                                                                                             
into                                                                                                                                                                                                                                             
tokens that I need