简体   繁体   中英

String Concatenation function in C doesn;t do anything, so what is the correct way?

I'm learning C language...

I want to write a function that concatenates two strings. I wrote a function but it doesn't work; it doesn't give any error in compilation, but while running it doesn't do anything.

Here is my code:

char* str_sum(char* s1, char* s2){
    int j = strlen(s1);
    int i=0;
    while(s2[i]){
            s1[j]=s2[i];
            j++;
            i++;
    }
    return s1;
}
int main(){
    char* s1, s2;
    s1 = "Joe";
    s2 = "Black";
    printf("%s\n",sum_str(s1,s2));
    return 0;
}

Your function could look like this:

char* sum_str(char* s1, char* s2)
{
    int lenS1 = strlen(s1);
    int lenS2 = strlen(s2);
    char* newString = malloc((lenS1 + lenS2 + 1) * sizeof(char));
    int i = 0;
    while(i < lenS1)
    {
        newString[i] = s1[i];
        i++;
    }
    while(i < lenS2 + lenS1)
    {
        newString[i] = s2[i - lenS1];
        i++;
    }
    newString[i] = '\0';
    return newString;
}

Note that this function allocates new string which means you should free this data when you finish with this string. Also note that terminating character ( '\\0' ) is stored at the end of this char array so that printf can "print" it properly.

Here's main:

int main()
{
  char *s1, *s2, *s3;
  s1 = "Joe";
  s2 = " Black";
  s3 = sum_str(s1,s2);
  printf("%s\n", s3);
  free(s3);
  return 0;
}

Output: Joe Black

Note that I have declared variables s1 , s2 and s3 like this: char *s1, *s2, *s3; . If I write it like this: char *s1, s2, s3; then variables s2 and s3 are no longer arrays of characters but only characters.

Also note that this program:

  char *s1 = "Joe";
  s1[0] = 'X';
  printf("%s\n", s1);

will crash since it tries to change constant string literal "Joe" . s1 is pointer to first character of this literal in this case.

But this program will work fine and its output will be Xoe :

  char s1[] = "Joe";
  s1[0] = 'X';
  printf("%s\n", s1);

s1 is an array initialized with string "Joe" so it's OK to change it.

Something like this:

char* str_sum(char* s1, char* s2){
   int len = strlen(s1) + strlen(s2);
   char* buff = malloc(len * sizeof(char) + 1);

   strcpy(buff, s1); //we don't need the zero termination char here.
   strcpy(buff + strlen(s1), s2);
   buff[len] = '\0';
   return buff;
}

Here's a way to do it without any predefined functions. The result of the concatenation is put into the third parameter of the function which is the result string:

  void str_cat_101(char const input1[], char const input2[], char result[])
  {
     int i, z;
     for(i = 0; input1[i] != 0; i++)
     {
        result[i] = input1[i];
     }
     for(z=0; input2[z] != 0; z++)
     {
        result[i+z] = input2[z];
     }
     result[i+z] = 0;
  }

There are 2 main issues with the code:

  1. string s1 could be pointing to read-only memory and can not be modified. Running your example on my machine cause a Segmentation Fault.
  2. string s1 is not large enough to hold the additional contents of s2. It should be declared as: char s1[30] = "Joe";

Your function doesn't allocate memory to write your new string. Maybe youcould use strcat or rewrite it like this:

char* str_sum(char* s1, char* s2) {
  int l1 = strlen(s1), l2 = strlen(s2), i;
  char sum = (char *)malloc(l1+l2+1);

  for(i=0; i<l1; i++) sum[i] = s1[i];
  for(i=0; i<l2; i++) sum[i+l1] = s2[i];

  sum[l1+l2] = '\0'; // NULL terminated    
  return sum;
}

Your str_sum function needs to create an array that is large enough to hold the contents of the concatenated strings.

char *str_sum( const char *s1, const char *s2 )
{
  char *ret = malloc( strlen(s1) + strlen(s2) + 1 ); // 1 for terminating NULL char

  if( ret == NULL ) {
    return NULL;
  }
  strcpy( ret, s1 );
  strcpy( &ret[strlen(s1)], s2 );
  return ret;
}

Also, the caller will need to free() the returned pointer (if it is not NULL).

You can do this either with strcat() or without (which is kind of meaningless but I include it for completeness sake. Refer to the example below.

char* str_sum_wstrcat(char* s1, char* s2)
{
    int len1 = strlen(s1);
    int len2 = strlen(s2);
    int i=0;
    char* sum = malloc(len1+len2+1);
    strcpy(sum,s1);
    strcat(sum,s2);


    return sum;
}

char* str_sum(char* s1, char* s2)
{
    int len1 = strlen(s1);
    int len2 = strlen(s2);
    int i=0;
    char* sum = malloc(len1+len2+1);
    strcpy(sum,s1);
    while(i<len2)
    {
        sum[len1+i] = s2[i];
        i++;
    }
    sum[len1+i]='\0';


    return sum;
}

int main()
{
  char* s1 = malloc(100);
  char* s2 = malloc(100);
  s1 = "Joe";
  s2 = "Black";
  printf("%s\n",str_sum(s1,s2));
  //or
  printf("%s\n",str_sum_wstrcat(s1,s2)); 
  return 0;
}

what you are doing will cause a segmentation fault. The string literals probably lie in the read only section of the memory. Its a run time error if you try to write to such a location. Use malloc instead as the other answers say. Its a mistake many beginners including myself make.

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM