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
),但希望这是一个好的开始。
我正在尝试编写一个方法,它接受一个字符串并根据分隔符字符串将其拆分为两个字符串,类似于 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
),但希望这是一个好的开始。