用C语言拆分字符串

时间:2015-04-13 01:46:44

标签: c string token

我想知道我们会将字符串拆分为令牌或任何其他有效的方法。

即。我有......

char string1[] = "hello\tfriend\n";

我如何在他们自己的独立变量中获得“你好”和“朋友”?

1 个答案:

答案 0 :(得分:2)

这是一个非常简单的示例,使用开始和结束指针将字符串拆分为保存在字符数组数组中的部分。 MAXLMAXW定义只是一种方便的方法来定义用于将单个字长限制为32(31个字符+空终止符)和最多3个字(部分)的常量。原始字符串:

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

#define MAXL 32
#define MAXW 3

int main (void) {

    char string1[] = "hello\tfriend\n";
    char *sp = string1;                 /* start pointer        */
    char *ep = string1;                 /* end pointer          */
    unsigned c = 0;                     /* temp character       */
    unsigned idx = 0;                   /* index for part       */
    char strings[MAXW][MAXL] = {{0}};   /* array to hold parts  */

    while (*ep)                         /* for each char in string1 */
    {
        if (*ep == '\t' || *ep == '\n') /* test if \t or \n         */
        {
            c = *ep;                    /* save character           */
            *ep = 0;                    /* replace with null-termator   */
            strcpy (strings[idx], sp);  /* copy part to strings array   */
            *ep = c;                    /* replace w/original character */
            idx++;                      /* increment index          */
            sp = ep + 1;                /* set start pointer        */
        }
        ep++;                           /* advance to next char     */
    }

    printf ("\nOriginal string1 : %s\n", string1);

    unsigned i = 0;
    for (i = 0; i < idx; i++)
        printf ("  strings[%u] : %s\n", i, strings[i]);

    return 0;
}

<强>输出

$ ./bin/split_hello

Original string1 : hello        friend

  strings[0] : hello
  strings[1] : friend

使用strtok只需用函数调用替换手动指针逻辑即可拆分字符串。


更新了行结束处理示例

正如您所发现的,当您单步执行字符串时,您可以创建一个简单的示例,因为您需要适应当前字符串,但只需稍加努力就可以扩展代码以处理更广泛的情况。在您的评论中,您注意到上述代码无法处理字符串末尾没有newline的情况。通过一些思考,您可以改进代码,以便处理这两种情况,而不是更改代码来处理这种情况。一种方法是:

    while (*ep)                         /* for each char in string1 */
    {
        if (*ep == '\t' || *ep == '\n') /* test if \t or \n         */
        {
            c = *ep;                    /* save character           */
            *ep = 0;                    /* replace with null-termator   */
            strcpy (strings[idx], sp);  /* copy part to strings array   */
            *ep = c;                    /* replace w/original character */
            idx++;                      /* increment index          */
            sp = ep + 1;                /* set start pointer        */
        }
        else if (!*(ep + 1))  {         /* check if next is ending  */
            strcpy (strings[idx], sp);  /* handle no ending '\n'    */
            idx++;
        }

        ep++;                           /* advance to next char     */
    }

打破任何格式/非打印字符

继续扩展可用于分隔字符串的字符,而不是使用离散值来识别哪些字符划分字,您可以使用一系列ASCII值将所有非打印或格式字符标识为分隔符。可以使用稍微不同的方法:

    char string1[] = "\n\nhello\t\tmy\tfriend\tagain\n\n";
    char *p = string1;                  /* pointer to char      */
    unsigned idx = 0;                   /* index for part       */
    unsigned i = 0;                     /* generic counter      */
    char strings[MAXW][MAXL] = {{0}};   /* array to hold parts  */

    while (*p)                          /* for each char in string1 */
    {
        if (idx == MAXW) {              /* test MAXW not exceeded   */
            fprintf (stderr, "error: MAXW (%d) words in string exceeded.\n", MAXW);
            break;
        }

        /* skip each non-print/format char */
        while (*p && (*p < ' ' || *p > '~'))
            p++;

        if (!*p) break;                 /* if end of s, break       */

        while (*p >= ' ' && *p <= '~')  /* for each printable char  */
        {
            strings[idx][i] = *p++;     /* copy to strings array    */
            i++;                        /* advance to next position */
        }

        strings[idx][i] = 0;            /* null-terminate strings   */
        idx++;                          /* next index in strings    */
        i = 0;                          /* start at beginning char  */
    }

这将处理您的测试字符串,无论行结束如何,无论包含的标签或换行符的数量如何。请查看ASCII Table and Description作为所用字符范围的参考。