CaTx
CaTx

Reputation: 1491

concatenate strings with memmove() in function

I want to concatenate two strings using a function that returns the resulting string. it would be something like this:

char *String_Concat (char *String_1, char *String_2)
{
    char *StringResult;

    //memmove String_1 to StringResult
    //memmove String_2 to StringResult

    return StringResult;
}

I wonder if that is a good way of doing that, since I know little about memory management. StringResult does not have a defined length, and I am not sure what will happen after two memmove operations.

I suppose StringResult will be cleaned up by the function itself, since I do not use malloc(), correct?

Upvotes: 1

Views: 1695

Answers (6)

alk
alk

Reputation: 70941

For completeness, assuming using memmove() was just an idea, not a requirement, strcpy() and strcat() are functions of choice here, as they are specially crafted to work on C-"strings", that is 0-terminated char-arrays.

#include  <stdlib.h> /* for malloc() */
#include  <string.h> /* for strcpy() and strcat() */
#include  <errno.h> /* for errno and EINVAL */

char * stralloc_and_cat(const char * s1, const char * s2)
{ 
  char * s = NULL;

  if ((NULL == s1) || (NULL == s2))
  {
    errno = EINVAL;
  }
  else 
  {
    if (NULL != (s = malloc(strlen(s1) + strlen(s2) + 1)))
    {
      strcpy(s, s1);
      strcat(s, s2);
    }
  }

  return s;
} 

And call it like this:

#include  <stdlib.h>
#include  <stdio.h>

char * stralloc_and_cat(const char * s1, const char * s2);

int main(void)
{
  char * s1 = "hello ";
  char * s2 = "world";

  char s = stralloc_and_cat(s1, s2);
  if (NULL == s)
  {
    perror("stralloc_and_cat() failed");
  }
  else
  {
    printf("%s\n", s);

    free(s);
  }

  return 0;
}

Upvotes: 0

user3185968
user3185968

Reputation:

char *String_Concat (char *String_1, char *String_2)
{
    size_t len1 = strlen(String_1);
    size_t len2 = strlen(String_2);
    char *StringResult = malloc(len1+len2+1);
    //might want to check for malloc-error...
    memcpy(StringResult, String_1, len1);
    memcpy(&StringResult[len1], String_2, len2+1);
    return StringResult;
}

So, C has the concept of storage for objects. The storage of an object determines its lifetime, as C is not garbage-collected. If you want to create a new string, You must reserve storage for it. The easiest way would be automatic storage, but that is associated with the scope of the function it is declared in, so automatic variables cease to exist after function return. Alternatively, you could use static storage, but that cannot be of variable size, and multiple calls to the function would use the same storage. Finally, you can use allocated storage, which requires malloc()/calloc()/realloc()/free().

See C11 draft standard, section 6.2.4 Storage durations of objects

Upvotes: 4

Mr.C64
Mr.C64

Reputation: 42964

You have to use malloc() to dynamically allocate some memory for the resulting concat string.
And in this case the caller is responsible to invoke free() to release the memory pointed by the returned string pointer.

An alternative would be to design a function expecting a pointer to a caller-allocated destination buffer, large enough to store the total resulting string.

Following the first option, you can consider code like this (live on Ideone):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// Concatenates string1 and string2.
// Returns the concatenated (string1+string2), or NULL on errors.
// NOTE: Memory for the returned string is allocated with malloc() 
// by the function, so the caller is responsible to release it with
// a call to free().
char *StringConcat(const char *string1, const char *string2)
{
    char *stringResult;
    size_t len1;
    size_t len2;

    // Check for NULL pointers...
    // (Return NULL, or whatever your design is...)
    if (string1 == NULL || string2 == NULL) {
        return NULL;
    }

    len1 = strlen(string1);
    len2 = strlen(string2);

    // +1 for terminating NUL ('\0')
    stringResult = malloc(len1 + len2 + 1);
    if (stringResult == NULL) {
        return NULL; // Allocation error
    }

    // Copy characters from first string    
    // (exclduing the terminating NUL --> len1)
    memcpy(stringResult, string1, len1);

    // Copy characters from second string
    // (including the terminating NUL --> len2+1)
    memcpy(stringResult + len1, string2, len2+1);

    // Return destination string pointer to the caller.
    // NOTE: Memory must be freed by the caller calling free().
    return stringResult;
}


// *** TEST ***
int main(void)
{
    // Test the function
    char * str = StringConcat("Hello ", "World");

    // Print the resulting string
    printf("%s\n", str);

    // Don't forget to free() memory allocatd by the concat function
    free(str);

    // All right
    return 0;
}

Upvotes: 0

Katie
Katie

Reputation: 1270

Here's how I would handle it, using existing string commands instead of memcpy. I'm assuming you want something like strcat that doesn't affect the source strings.

char* string_concat(char *dest, const char* string1, const char* string2)
{
   strcpy(dest, string1);
   strcat(dest, string2);
   return dest;
}

To use it, you need to pass in a pointer to the buffer you want the result stored in. You can use malloc to make it the size you need. Free it when you're done.

char *str1 = "abc";
char *str2 = "def";
size_t len = strlen(str1) + strlen(str2);
char *newstr = malloc(len + 1);
string_concat(newstr, str1, str2);
printf("%s\n", newstr);
free(newstr);

There is simply no way to deal with arbitrary-length strings without allocating memory, so you'll be stuck with malloc/free unless you're using character arrays with fixed lengths. If you want to abstract the logic of deciding how big of a buffer to allocate you can do something like this:

size_t string_concat(char* dest, char* string1, char* string2)
{
   if(!dest)
   {
      return strlen(string1) + strlen(string2) + 1;
   }
   strcpy(dest, string1);
   strcat(dest, string2);
   return 0;
}

Then you can ask it how much to allocate like this:

char* newstr = malloc(string_concat(0, str1, str2));

But you lose the syntactical convenience of it returning a pointer to dest.

Upvotes: 2

Iharob Al Asimi
Iharob Al Asimi

Reputation: 53006

If you want to avoid dynamic allocation you can do something like

int main( int argc, char **argv)
{
    char        String_1[8] = "Exa";
    /*                   ^ enough space for Example\0 */
    const char *String_2    = "mple";

    printf("%s\n", strcat(String_1, String_2));

    return 0;
}

Upvotes: 0

unwind
unwind

Reputation: 399863

It's a very bad idea, and no "cleaning" will magically happen by the function.

You cannot do this, it's not a valid way to implement string concatenation in C.

You must make sure there's enough writable memory before doing anything, so in general you must call malloc().

Upvotes: 0

Related Questions