I'm trying to paste two strings together. I know you can do it faster but I'm not allowed to use build-in functions. I allocate memory for string3 and in main the memory should be released but it is not. I'm not allowed to change anything in main. What am I doing wrong?
Allocating memory happens here:
char *string_cat( char const *string1, char const *string2 )
{
int lengte1 = string_length(string1);
int lengte2 = string_length(string2);
int totaal_lengte = lengte1 lengte2;
char *string3 = (char*) malloc(totaal_lengte*sizeof(char));
int i = 0;
int j = 0;
while(string1[i] != '\0'){
string3[j] = string1[i];
i ;
j ;
}
i = 0;
while(string2[i] != '\0'){
string3[j] = string2[i];
i ;
j ;
}
return string3;
}
Freeing memory happens here:
int main( int argc, char **argv )
{
char *str;
printf( "== string_cat ==\n" );
check( strcmp( ( str = string_cat( "", "" ) ) == NULL ? "" : str, "" ) == 0, __FILE__, __LINE__ ); free( str );
check( strcmp( ( str = string_cat( "", "abcdef" ) ) == NULL ? "" : str, "abcdef" ) == 0, __FILE__, __LINE__ ); free( str );
check( strcmp( ( str = string_cat( "a", "bcdef" ) ) == NULL ? "" : str, "abcdef" ) == 0, __FILE__, __LINE__ ); free( str );
check( strcmp( ( str = string_cat( "ab", "cdef" ) ) == NULL ? "" : str, "abcdef" ) == 0, __FILE__, __LINE__ ); free( str );
check( strcmp( ( str = string_cat( "abc", "def" ) ) == NULL ? "" : str, "abcdef" ) == 0, __FILE__, __LINE__ ); free( str );
check( strcmp( ( str = string_cat( "abcd", "ef" ) ) == NULL ? "" : str, "abcdef" ) == 0, __FILE__, __LINE__ ); free( str );
check( strcmp( ( str = string_cat( "abcde", "f" ) ) == NULL ? "" : str, "abcdef" ) == 0, __FILE__, __LINE__ ); free( str );
check( strcmp( ( str = string_cat( "abcdef", "" ) ) == NULL ? "" : str, "abcdef" ) == 0, __FILE__, __LINE__ ); free( str );
return 0;
}
CodePudding user response:
- Do not cast the result of
malloc
. It you are getting the error it means that you compile C code using C compiler which is not right. - You need extra space for null terminating character.
sizeof(char)
is by definition 1, but if you want to check it (for example strings can be multibyte chars - use objects not types insizeof
- Use the correct type for size (ie
size_t
) - You can modify while loops to include null terminating character in the last copy
- Chech the result of malloc
- It is good to check if parameters are OK
size_t string_length(const char *s)
{
const char *end = s;
while(*end) end ;
return end - s;
}
char *string_cat( char const *string1, char const *string2 )
{
char *string3 = NULL;
if(string1 && string2)
{
size_t lengte1 = string_length(string1);
size_t lengte2 = string_length(string2);
size_t totaal_lengte = lengte1 lengte2;
char *tmp;
string3 = malloc((totaal_lengte 1) * sizeof(*string3));
if(string3)
{
tmp = string3;
while(*string1) *tmp = *string1 ;
while((*tmp = *string2 ));
}
}
return string3;
}
CodePudding user response:
- You need to allocate the memory 1, with malloc you maybe need to set
the last value to '\0' with calloc it will initialize the memory
to zero. - You can override the default functions with your own, not a big thing but helps with reading the code.
- Its better to compare constants first to the variable like '\0' == val, this will prevent mistakes like val = '\0'.
- Put free on a new line, this is for readability and makes things less confusing.
- This is more of personal opinion, but I don't see the need for space between brackets as it just increases the file size with no benefit, instead I would use new lines more.
- Its stated and is a minor thing but casting from void to char is not a C thing.
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
size_t strlen(char const* str) {
size_t i;
for (i = 0; '\0' != str[i]; i );
return i;
}
void* memcpy(void* restrict dst, const void* restrict src, size_t bytes) {
char* d = dst;
const char* s = src;
for (int i = 0; i < bytes; i ) {
d[i] = s[i];
}
return d;
}
char* string_cat(char const* str1, char const* str2) {
int len1 = strlen(str1);
int len2 = strlen(str2);
/// calloc will set memory block to zero
char* out = calloc(1, len1 len2 1);
memcpy(out, str1, len1);
memcpy(&out[len1], str2, len2);
return out;
}
int check(int state, const char* file, int line) {
if (!state) {
printf("File %s on line %d is not the same\n", file, line);
}
return 0;
}
int main(int argc, char **argv) {
char *str;
printf("== string_cat ==\n");
check(strcmp((str = string_cat("", "")) == NULL
? "" : str, "") == 0, __FILE__, __LINE__);
free(str);
check(strcmp((str = string_cat("", "abcdef")) == NULL
? "" : str, "abcdef") == 0, __FILE__, __LINE__);
free(str);
check(strcmp((str = string_cat("a", "bcdef")) == NULL
? "" : str, "abcdef") == 0, __FILE__, __LINE__);
free(str);
check(strcmp((str = string_cat("ab", "cdef")) == NULL
? "" : str, "abcdef") == 0, __FILE__, __LINE__);
free(str);
check(strcmp((str = string_cat("abc", "def")) == NULL
? "" : str, "abcdef") == 0, __FILE__, __LINE__);
free(str);
check(strcmp((str = string_cat("abcd", "ef")) == NULL
? "" : str, "abcdef") == 0, __FILE__, __LINE__);
free(str);
check(strcmp((str = string_cat("abcde", "f")) == NULL
? "" : str, "abcdef") == 0, __FILE__, __LINE__);
free(str);
check(strcmp((str = string_cat("abcdef", "")) == NULL
? "" : str, "abcdef") == 0, __FILE__, __LINE__);
free(str);
return 0;
}