ОБНОВЛЕНИЕ 2 : Дэйв добавил проверку ошибок в своем предложении, я принял ее и добавил немного расширенную функциональность, в отдельном ответе.
ОБНОВЛЕНИЕ 1 : Проблема решена (это был не realloc (), это был факт, что я не выделял дополнительный слот таблицы для завершения NULL ... Я исправил это).См. Также предложение Дейва в 1-м ответе
Исходное сообщение :
Возможно ли динамически перераспределить совершенно неизвестную таблицу строк в c, не используя промежуточныйструктуры данных?
То, что я хочу сделать, это создать функцию sarr_make_tokens () для токенизации произвольной строки c и возврата таблицы (завершенных NULL) токенов строки c.
ДляНапример, с s [] = "Привет жестокий мир!"и вызов: char ** tokens = s_make_tokens (s, "\ t!");Я хотел бы получить таблицу токенов, заканчивающуюся на NULL ...
tokens[0] : "hello"
tokens[1] : "cruel"
tokens[2] : "world"
tokens[3] : NULL
Часть кода, приведенная ниже, не работает (в строке realloc (), я думаю), но я не могу вспомнить размер, который должен передатьчтобы сохранить все уже сохраненные токены.
Возможно ли это вообще, или мне нужно сначала получить количество токенов с помощью цикла strok () на локальной копии s, затем mallocсколько слотов в таблице токенов, а затем применить другой цикл strtok (), чтобы сохранить фактические токены в таблице?
Я мог бы использовать промежуточный связанный список для хранения токенов, прежде чем копировать их в токены.таблица, но если есть способ использовать realloc с правильным размером, было бы намного лучше!
Буду признателен за любую помощь!Вот проблемный код ... на самом деле он работает, но ошибки при попытке освободить () полученную таблицу токенов в функции вызывающей стороны.
#define S_FREE(p) \
do \
if ( (p) ) { \
free( (p) ); \
(p) = NULL; \
} \
while (0)
/* --------------------------------------------- */
int sarr_free( char *sarr[] )
{
register char **cpp = sarr;
/* sanity check */
if ( !sarr ) { errno = EFAULT; return 0; }
while ( *cpp )
free( *cpp++ );
free( sarr );
return 1; /* TRUE */
}
/* --------------------------------------------- */
char **sarr_make_tokens( char *s, const char *delims )
{
char **tokens = NULL, **ppchar = NULL;
size_t toksize = 0;
register char *cp = NULL;
register int i=0, j=0;
/* sanity checks */
if ( !s || !delims ) { errno = EFAULT; return NULL; }
if ( !*s || !*delims ) { errno = EINVAL; return NULL; }
i = 0;
cp = strtok( s, delims );
while ( cp != NULL )
{
/* add a new slot in the array */
ppchar = realloc( tokens, (i+1) * sizeof(char *) );
if ( !ppchar ) {
for (j=i-1; j > -1; j--)
free( tokens[j] );
S_FREE( tokens );
errno = ENOMEM;
return NULL;
}
tokens = ppchar;
/* make room for the token & copy it into the slot */
toksize = strlen( cp ) + 1;
tokens[i] = calloc( toksize, sizeof(char) );
if ( !tokens[i] ) {
for (j=i-1; j > -1; j--)
free( tokens[j] );
free( tokens );
errno = ENOMEM;
return NULL;
}
memcpy( tokens[i], cp, toksize );
/* get next token */
cp = strtok( NULL, delims );
i++;
}
if ( i != 0 ) { /* while-loop run at least once */
ppchar = realloc( tokens, (i+1) * sizeof(char *) );
if ( !ppchar )
/* handle error here */
tokens = ppchar;
tokens[ i ] = NULL; /* ... NULL terminate the array of tokens */
}
else /* while-loop did not run at all */
errno = ERANGE; /* ... flag failure of 1st strtok() */
return tokens;
}