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

C:将一个字符串拆分为两个字符串,并返回一个2元素数组,c,pointers,c-strings,strtok,C,Pointers,C Strings,Strtok,我正在尝试编写一个方法,该方法接受一个字符串并基于分隔符字符串将其拆分为两个字符串,类似于Java中的.split: char * split(char *tosplit, char *culprit) { char *couple[2] = {"", ""}; int i = 0; // Returns first token char *token = strtok(tosplit, culprit); while (toke

我正在尝试编写一个方法,该方法接受一个字符串并基于分隔符字符串将其拆分为两个字符串,类似于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;
} 
。。。当然,这种方法并不像我希望的那样有效

我做错了什么


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

耦合的类型是
char**
,但是您已经将函数返回类型定义为
char*
。此外,您将返回指向局部变量的指针。您需要将指针数组从调用方传递到函数中。例如:

#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;
}
#包括
#包括
字符**分裂(字符**成对,字符*分裂,字符*罪犯)
{ 
int i=0;
//返回第一个令牌
char*token=strtok(tosplit,罪犯);
对于(inti=0;令牌!=NULL&&i<2;i++)
{ 
偶[i]=令牌;
令牌=strtok(空,罪魁祸首);
} 
返回夫妇;
} 
int main()
{
char*couple[2]={“”“”};
char-tosplit[]=“你好,世界”;
字符**字符串=拆分(耦合,tosplit,“”);
printf(“%s,%s”,字符串[0],字符串[1]);
返回0;
}
查看物品:

首先,返回一个指向字符(序列)的指针,即
char
*
而不是指向char的(一系列)指针的指针。因此,返回类型应该是
char**

第二,返回局部变量的地址,一旦函数完成,它就超出范围,以后不能访问

第三,您定义了一个由2个指针组成的数组,而
while
-循环的写操作可能会超出这些界限

如果确实要将字符串拆分为两个字符串,则应使用以下方法:

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 );
}
#包括
#包括
char*split(char*s,char*delim){
字符*指针=strstr(s,delim);
如果(!针)
返回NULL;
针[0]=0;
回针+斯特伦(德利姆);
}
int main(){
char s[]=“毛茸茸的小兔子!”;
char*res=分裂(s,“毛茸茸的”);
printf(“%s%s\n”,s,res);
}

它会打印出“毛茸茸的兔子!”。

首先,strtok会修改
的内存以拆分
,所以一定要确定,这就是你想要做的。如果是这样,那么考虑一下:

#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++;
    }

}
#包括
#包括
#包括
/* 
*注意:使用strtok的实现不安全(且存在漏洞)
*
**into必须指向可存储令牌的内存空间
*或者,如果*into为NULL,则它会分配足够的空间。
*返回:
*已分配您必须释放的项目数组
*
*/
字符**\u拆分(字符*src,常量字符*delim)
{
大小\u t idx=0;
char*next;
char**dest=NULL;
做{
dest=realloc(dest,(idx+1)*sizeof(char*);
next=strtok(idx>0?NULL:strdup(src),delim);
dest[idx++]=next;
}while(next);
返回目的地;
}
int main(){
int x=0;
char**here=NULL;
这里=uu split(“你好,你好,你好吗?”,“,”);
而(此处[x]){
printf(“此处:%s\n”,此处[x]);
x++;
}
}

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

函数返回类型是
char*
,您返回的是一个char*
数组,正如警告所说,您返回的是一个局部变量的地址。你不能那样做。您需要动态分配一个数组或将其作为参数。另外,您声明返回单个字符串,而不是字符串数组。
couple
在函数退出时超出范围,事实上已经不存在了。您想要字符串部分的独立副本,还是指向原始字符串的指针就足够了?@Swardfish我正在寻找独立副本。这似乎只会返回两个指向字符串开头的指针。@Stephan Lechner这不会在这对字符串中返回原始字符串本身[0]位置?语义与最初的意图略有不同,没有找到任何分隔符会导致两个空字符串。但是,这种设计更简单,如果没有分隔符,则至少返回一个字符串,并在第二个字符串中返回一个空指针。我认为这更好,但可能有一个原因,原来的语义;循环条件
i<2
确保只写入
couple[0]和
couple[1]`。当我尝试从main使用您的方法时,如下所示:char*result=*split(“what/in”、“/”;printf(“%c\n”,结果[0]);printf(“%c\n”,结果[1]);我遇到了一个分段错误。当您将指针的第一个字符设置为NULL时,您所做的操作与
strtok
所做的完全相同。是和否。这确实遵循了修改原始字符串的C传统,但它基于字符串分隔符进行拆分(每个Java)。所有以两个下划线开头的名称都保留供实现使用。您可以在自己的代码中忽略此规则(并承担后果),但请不要在可能被不太了解此规则的人复制的地方执行此规则。
#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++;
    }

}