C:将一个字符串拆分为两个字符串,返回一个2元数组

C: Splitting a string into two strings, and returning a 2 - element array

我正在尝试编写一个方法,它接受一个字符串并根据分隔符字符串将其拆分为两个字符串,类似于 Java 中的 .split:

char * split(char *tosplit, char *culprit) { 

    char *couple[2] = {"", ""};

    int i = 0; 

    // Returns first token  
    char *token = strtok(tosplit, culprit);    


    while (token != NULL && i < 2) { 
        couple[i++] = token; 
        token = strtok(NULL, culprit); 
    } 

    return couple;
} 

但我不断收到警告:

In function ‘split’:
warning: return from incompatible pointer type [-Wincompatible-pointer-types]
     return couple;
            ^~~~~~
warning: function returns address of local variable [-Wreturn-local-addr]

...当然这个方法并没有像我希望的那样起作用。

我做错了什么?

编辑:除了使用 strtok() 之外,我也愿意接受其他方法。

couple 的类型是 char** 但您已将函数 return 类型定义为 char*。此外,您正在 return 指向局部变量的指针。您需要将指针数组从调用者传递到函数中。例如:

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

char** split( char** couple, char* tosplit, char* culprit ) 
{ 
    int i = 0; 

    // Returns first token  
    char *token = strtok( tosplit, culprit);    

    for( int i = 0; token != NULL && i < 2; i++ ) 
    { 
        couple[i] = token; 
        token = strtok(NULL, culprit); 
    } 

    return couple;
} 

int main()
{
    char* couple[2] = {"", ""};
    char tosplit[] = "Hello World" ;

    char** strings = split( couple, tosplit, " " ) ;

    printf( "%s, %s", strings[0], strings[1] ) ;

    return 0;
}

一览事物:

首先,您 return 指向字符(序列)的指针,即 char * 而不是指向字符(序列)的指针字符。因此,return 类型应该是 char **

其次,你 return 局部变量的地址,一旦函数完成 - 超出范围,之后不得访问。

第三,您定义了一个包含 2 个指针的数组,而您的 while-loop 可能会超出这些范围。

如果你真的想拆分成两个字符串,下面的方法应该可行:

char ** split(char *tosplit, char *culprit) {     
    static char *couple[2];
    if ((couple[0] = strtok(tosplit, culprit)) != NULL) {
        couple[1] = strtok(NULL, culprit);
    }
    return couple;
} 

请注意您对 strtok 的使用,它可能无法满足您的要求。如果您认为它的作用类似于 Java 拆分,请阅读手册页,然后再重新阅读七遍。它实际上是根据 delim 中的任何值对字符串进行标记。

我想你正在寻找这样的东西:

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

char* split( char* s, char* delim ) {
  char* needle = strstr(s, delim);

  if (!needle)
    return NULL;

  needle[0] = 0;
  return needle + strlen(delim);
}

int main() {
  char s[] = "Fluffy furry Bunnies!";
  char* res = split(s, "furry ");
  printf("%s%s\n", s, res );
}

打印出 "Fluffy Bunnies!".

首先,strtok 修改了 tosplit 的内存,因此请确定,这就是您想要做的。如果是这样,那么考虑一下:

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

/* 
 * NOTE: unsafe (and leaky) implementation using strtok
 *
 * *into must point to a memory space where tokens can be stored
 * or if *into is NULL then it allocates enough space.
 * Returns:
 *  allocated array of items that you must free yourself
 *
 */


char **__split(char *src, const char *delim)
{
    size_t idx = 0;
    char *next;
    char **dest = NULL;


    do {
        dest = realloc(dest, (idx + 1)* sizeof(char *));
        next = strtok(idx > 0 ? NULL:strdup(src), delim);
        dest[idx++] = next;
    } while(next);


    return dest; 
}


int main() {
    int x = 0;
    char **here = NULL;
    here = __split("hello,there,how,,are,you?", ",");

    while(here[x]) {
        printf("here: %s\n", here[x]);
        x++;
    }

}

您可以实现一个更安全且无泄漏的版本(注意 strdup),但希望这是一个好的开始。