I have experienced an issue while using strcat, using realloc however, strcat overwrites destination string
char *splitStr(char *line) {
char *str_;
str_ = (char *) malloc(1);
char *ptr = strtok(line,"\n");
int a;
while (ptr != NULL) {
if (ptr[0] != '$') {
printf("oncesi %s\n", str_);
a = strlen(ptr) + strlen(str_) + 1;
str_ = realloc(str_, a);
strcat(str_, ptr);
str_[a] = '\0';
printf("sontasi:%s\n", str_);
}
ptr = strtok(NULL, "\n");
}
printf("splitStr %d\n", strlen(str_));
printf("%s", str_);
return str_;
}
and my input value is ;
*4
$3
200
$4
4814
$7
SUCCESS
$4
3204
so I want to split this input value via strtok; strtok(line,'\\n');
and concat all line without start "$" char to new char. However, this code give following output;
line: *4
oncesi
sontasi:*4
oncesi *4
200tasi:*4
200esi *4
4814asi:*4
4814si *4
SUCCESS:*4
SUCCESS*4
3204ESS:*4
splitStr 25
seems to overwrite source string. do you have any idea why this issue could be happening ?
the following proposed code:
malloc()
and realloc()
strlen()
returns a size_t
, not an int
. so the proper output format conversion specifier is: %zu
and now, the proposed code:
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
char *splitStr( char *line )
{
printf("original line: %s\n", line);
char *str = malloc(1);
if( !str )
{
perror( "malloc failed" );
exit( EXIT_FAILURE );
}
str[0] = '\0'; // critical statement
char *token = strtok(line,"\n");
while( token )
{
if( token[0] != '$')
{
char* temp = realloc( str, strlen( token ) + strlen( str ) + 1 );
if( ! temp )
{
perror( "realloc failed" );
free( str );
exit( EXIT_FAILURE );
}
str = temp; // update pointer
strcat(str, token);
printf( "concat result: %s\n", str );
}
token = strtok(NULL, "\n");
}
printf("splitStr %zu\n", strlen(str));
return str;
}
int main( void )
{
char firstStr[] = "$abcd\n$defg\nhijk\n";
char *firstNewStr = splitStr( firstStr );
printf( "returned: %s\n\n\n\n", firstNewStr );
free( firstNewStr );
char secondStr[] = "abcd\ndefg\nhijk\n";
char *secondNewStr = splitStr( secondStr );
printf( "returned: %s\n\n\n\n", secondNewStr );
free( secondNewStr );
}
a run of the proposed code results in:
original line: $abcd
$defg
hijk
concat result: hijk
splitStr 4
returned: hijk
original line: abcd
defg
hijk
concat result: abcd
concat result: abcddefg
concat result: abcddefghijk
splitStr 12
returned: abcddefghijk
Your input contains Windows/DOS end-of-line codings "\\r\\n"
.
Since strtok()
just replaces '\\n'
with '\\0'
, the '\\r'
stays in the string. On output it moves the cursor to the left and additional characters overwrite old characters, at least visually.
Your concatenated string should be OK, however. Count the characters, and don't forget to include a '\\r'
for each line: "*4\\r200\\r4814\\rSUCCESS\\r3204\\r"
are 25 characters as the output splitStr 25
shows.
Additional notes:
str_ = (char *) malloc(1);
does not initialize the space str_
points to. You need to do this yourself, in example by str_[0] = '\\0';
. malloc()
, it is a void*
that is compatible to char*
(and any other).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.