问题描述
因此,我正在尝试构建一个string_split
函数以基于分隔符来拆分c样式的字符串。
char** string_split(char* input,char delim)
{
char** split_strings = malloc(sizeof(char*));
char* charPtr;
size_t split_idx = 0;
int extend = 0;
for(charPtr = input; *charPtr != '\0'; ++charPtr)
{
if(*charPtr == delim || *(charPtr+1) == '\0')
{
if(*(charPtr+1) == '\0') extend = 1; //extend the range by one for the null byte at the end
char* string_element = calloc(1,sizeof(char));
for(size_t i = 0; input != charPtr+extend; ++input,++i)
{
if(string_element[i] == '\0')
{
//allocate another char and add a null byte to the end
string_element = realloc(string_element,sizeof(char) * (sizeof(string_element)/sizeof(char) + 1));
string_element[i+1] = '\0';
}
string_element[i] = *input;
}
printf("string elem: %s\n",string_element);
split_strings[split_idx++] = string_element;
//allocate another c-string if we're not at the end of the input
split_strings = realloc(split_strings,sizeof(char*) *(sizeof(split_strings)/sizeof(char*) + 1));
//skip over the delimiter
input++;
extend = 0;
}
}
free(charPtr);
free(input);
return split_strings;
}
本质上,它的工作方式是有两个char*
,input
和charPtr
。 charPtr
从输入字符串的开头算起下一个分隔符实例,然后input
从分隔符的上一个实例(或输入字符串开头)算起,并复制每个{ {1}}改成新的char
。构建字符串后,会将其添加到char*
数组中。
还有一些第二个位,用于跳过定界符并处理输入字符串的端点。该功能的用法如下:
char**
无论如何,它大部分工作,除了返回的int main()
{
char* str = "mon,tue,wed,thur,fri";
char delim = ',';
char** split = string_split(str,delim);
return 1;
}
数组中的第一个char*
已损坏,而只是被随机垃圾占据。
例如,从char**
打印split
的元素将产生:
main
奇怪的是,split: α↨▓
split: tue
split: wed
split: thur
split: fri
的内容(split_strings[0]
的数组返回了所需的标记)是char*
,就本例而言,一直到最后循环mon
函数中主要for循环的内容,特别是其行:
string_split
会将其内容从split_strings[split_idx++] = string_element;
变为垃圾邮件。谢谢您的任何帮助。
解决方法
任何人都想知道的最终功能应该是非常简单的证明。
char** string_split(char* input,char delim,bool skip_delim)
{
assert(*input != '\0');
char** split_strings = malloc(sizeof(char*));
char* charPtr;
size_t split_idx = 0;
size_t num_allocated_strings = 1;
size_t extend = 0;
for(charPtr = input; *charPtr != '\0'; ++charPtr)
{
if(*charPtr == delim || *(charPtr+1) == '\0')
{
if(*(charPtr+1) == '\0') extend = 1; //extend the range by one for the null byte at the end
char* string_element = calloc(1,sizeof(char));
for(size_t i = 0; input != charPtr+extend; ++input,++i)
{
if(string_element[i] == '\0')
{
//allocate another char and add a null byte to the end
char* temp = realloc(string_element,sizeof(char) * (strlen(string_element) + 1));
if(temp == NULL)
{
free(string_element);
free(split_strings);
break;
}
string_element = temp;
string_element[i+1] = '\0';
}
string_element[i] = *input;
}
split_strings[split_idx++] = string_element;
num_allocated_strings++;
//allocate another c-string
char** temp = realloc(split_strings,sizeof(char*) * num_allocated_strings);
if(temp == NULL)
{
free(string_element);
free(split_strings);
break;
}
split_strings = temp;
//skip over the delimiter if required
if(skip_delim) input++;
extend = 0;
}
}
split_strings[num_allocated_strings-1] = NULL;
return split_strings;
}
,
您的函数至少是不正确的,因为它试图释放传递的字符串
char** string_split(char* input,char delim)
{
//...
free(charPtr);
free(input);
return split_strings;
}
在您的程序中是字符串文字
char* str = "mon,tue,wed,thur,fri";
char delim = ',';
char** split = string_split(str,delim);
您可能无法释放字符串文字。
第一个参数应具有限定符const
。
函数中还有许多其他错误。
例如,该语句中使用的表达式sizeof(string_element)/sizeof(char)
string_element = realloc(string_element,sizeof(char) * (sizeof(string_element)/sizeof(char) + 1));
不会产生早期分配给指针string_element
所指向的数组的字符数。并且没有必要为每个新字符重新分配数组。
例如,该函数可以通过以下演示程序中的以下方式查看。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char ** string_split( const char *s,char delim )
{
size_t n = 1;
char **a = calloc( n,sizeof( char * ) );
while ( *s )
{
const char *p = strchr( s,delim );
if ( p == NULL ) p = s + strlen( s );
if ( p != s )
{
char *t = malloc( p - s + 1 );
if ( t != NULL )
{
memcpy( t,s,p - s );
t[p-s] = '\0';
}
char **tmp = realloc( a,( n + 1 ) * sizeof( char * ) );
if ( tmp == NULL )
{
free( t );
break;
}
a = tmp;
a[n-1] = t;
a[n] = NULL;
++n;
}
s = p + ( *p != '\0' );
}
return a;
}
int main(void)
{
char* str = "mon,fri";
char delim = ',';
char **split = string_split( str,delim );
for ( char **p = split; *p != NULL; ++p )
{
puts( *p );
}
for ( char **p = split; *p != NULL; ++p ) free( *p );
free( split );
return 0;
}
程序输出为
mon
tue
wed
thur
fri