New to c and trying to learn. Here I tried to create a function that copies a string until first space using dynamic memory allocation and byref. Seems like I'm doing something wrong with the way I used realloc. Can you help me figure out what is wrong with the way I used dynamic memory allocation?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void f1(char **c, char *s);
int main() {
char * s = "this is an example";
char *c;
c =(char *) malloc(sizeof(char));
f1(&c,s);
free(c);
}
void f1(char **c, char *s)
{
int i=0;
while ((s[i])!=' ')
{
(*c)[i]=s[i];
i ;
(*c)=(char *)realloc ((*c),sizeof(char)*i);
}
(*c)[i]='\0';
printf("\n%s\n",*c);
}
CodePudding user response:
void f1(char** r, char* s)
{
// find size of new buffer
size_t len = 0;
while(s[len] != '\0' && s[len] != ' ') len ;
*r = (char*)malloc(len 1);
memcpy(*r, s, len);
(*r)[len] = '\0';
}
CodePudding user response:
Before the function call there was already allocated memory for one character
c =(char *) malloc(sizeof(char));
In the first iteration of the while loop
int i=0;
while ((s[i])!=' ')
{
(*c)[i]=s[i];
i ;
(*c)=(char *)realloc ((*c),sizeof(char)*i);
}
this memory was filled
(*c)[i]=s[i];
and then again there was allocated memory only for one character
(*c)=(char *)realloc ((*c),sizeof(char)*i);
because in the first iteration of the loop i
becomes equal to 1
. So in the second iteration of the loop there is an attempt to write outside the allocated memory that results in undefined behavior.
You need to write at least like
*c = realloc ( *c, i 1);
Also it will be more safer to use an intermediate pointer as for example
char *tmp = realloc ( *c, i 1);
if ( tmp != NULL ) *c = tmp;
but in this case you will need also to change the function logic.
And the function should be declared like
int f1( char **c, const char *s);
and the condition of the should be changed like
while ( s[i] != '\0' && s[i] !=' ' )
Using your approach the program can look the following way.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int f1( char **s1, const char *s2 );
int main( void )
{
const char *s = "this is an example";
char *t = malloc( sizeof( char ) );
if ( t != NULL )
{
t[0] = '\0';
f1( &t, s);
puts( t );
}
free( t );
}
int f1( char **s1, const char *s2 )
{
int success = 1;
for ( size_t i = 0; success && s2[i] != '\0' && !isblank( ( unsigned char )s2[i] ); i )
{
char *tmp = realloc( *s1, i 2 );
success = tmp != NULL;
if ( success )
{
*s1 = tmp;
( *s1 )[i] = s2[i];
( *s1 )[i 1] = '\0';
}
}
return success;
}
The program output is
this
However such an approach with many memory reallocations is inefficient.
I would write the program the following way
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char * f1( const char *s, const char *delim );
int main( void )
{
const char *s = "this is an example";
char *t = f1( s, " \t" );
if ( t != NULL )
{
puts( t );
}
free( t );
}
char * f1( const char *s, const char *delim )
{
size_t n = strcspn( s, delim );
char *result = malloc( n 1 );
if ( result != NULL )
{
result[n] = '\0';
memcpy( result, s, n );
}
return result;
}
Again the program output is
this
CodePudding user response:
As @UnholySheep mentioned the i
I used to allocate memory was too small. Changed to (*t) = (char *)realloc((*t),(i 1)*sizeof(char));
and it worked.
CodePudding user response:
In this code, there is a committed mistake regarding using a double pointer. A double pointer should be used only to create an array of arrays. According to your purpose, you should use a single pointer to represent the array to copy to. Also, you need to create another function that counts the length of the string you want to copy before creating the string to copy to.