0

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;
    }
Jef
  • 11
  • 1
  • 1
    Don't post pictures of code. Post code as properly formatted text. [Edit] your question. – Jabberwocky Aug 09 '22 at 07:20
  • 2
    Hint: the memory space required for a string is the length of the string **plus one** for the null terminator. – Jabberwocky Aug 09 '22 at 07:22
  • 1
    You do seem to remember that strings in C are null-terminated. But you have forgotten that this null-terminator is not counted by `strlen` and that you need to allocate space for it as well. So a string of `X` character needs space for `X + 1` to include the null-terminator. – Some programmer dude Aug 09 '22 at 07:22
  • And, kinda like Beyoncé sang, not only do you need space for the extra char, but you gotta "put a ring on it..." (ie. fill that extra char with '\0'...) Otherwise it's just an array of characters, not a "string"... – Fe2O3 Aug 09 '22 at 07:27
  • Does this answer your question? [What are null-terminated strings?](https://stackoverflow.com/questions/72436704/what-are-null-terminated-strings) – n. m. could be an AI Aug 09 '22 at 08:15

2 Answers2

4
  1. 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.
  2. You need extra space for null terminating character.
  3. sizeof(char) is by definition 1, but if you want to check it (for example strings can be multibyte chars - use objects not types in sizeof
  4. Use the correct type for size (ie size_t)
  5. You can modify while loops to include null terminating character in the last copy
  6. Chech the result of malloc
  7. 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;
}
0___________
  • 60,014
  • 4
  • 34
  • 74
0
  • 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;
}
Xenose
  • 1
  • 1