Parth Rajawat
Parth Rajawat

Reputation: 75

Unable to concatenate two strings

I was practicing on the topics of string. I am trying to concatenate two strings without using the strcat() function available in C.

This is the code that I came up with:

#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <ctype.h>

int string_length();
void concatenate();

int main(void) {
    char str[] = "Hello there";
    char str2[] = "How are you";
    char result[100];
    int length;

    length = string_length(str);

    printf("%d\n", length);
    concatenate(result, str, str2);
}

//Function which counts the number of characters of the string
int string_length(char str[]) {
    int i = 0;
    while (str[i] != '\0') {
        i++;
    }
    return i;
}

//Function to concatenate the two strings
void concatenate(char result[], char str[], char str2[]) {
    int i = 0;
    while (str[i] != '\0') {
        result[i] = str[i];
        ++i;
    }
    int j = i + 2, k = 0;
    while (str2[k] != '\0') {
        result[j] = str2[k];
        k++;
        j++;
    }
    printf("%s\n", result);
}

When I ran this code, this is what I get as the output -

    11
    Hello there

The concatenation function is not working properly as output should be-

    11
    Hello there How are you

I used the debugger and found that loops are working fine and as per the counter variable, The two strings should get concatenated.

Upvotes: 1

Views: 450

Answers (4)

chqrlie
chqrlie

Reputation: 144780

There are multiple problems in your code:

  • in your concatenation function, you initialize j to i + 2, whereas you should just use j = i as the first character of the second string should come just after the last character of the first and i was incremented after each character copied from str. Note that you can just use i, there is no need for j.
  • you must set the null terminator at the end of result. You can set at with result[j] = '\0';
  • you should output the concatenated string in main instead of concatenate().
  • the prototypes of string_length() and concatenate() should include the argument types.

Also note that you should use size_t for the index types.

Here is a modified version:

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

size_t string_length(const char *s);
void concatenate(char *result, const char *str, const char *str2);

int main(void) {
    char str[] = "Hello there";
    char str2[] = "How are you";
    char result[100];
    size_t length;

    length = string_length(str);

    printf("%zu\n", length);
    concatenate(result, str, str2);
    printf("%s\n", result);  // shows Hello thereHow are you
    concatenate(result, "abc", "def");
    printf("%s\n", result);  // shows abcdef
    return 0;
}

//Function which counts the number of characters of the string
size_t string_length(const char *s) {
    size_t i = 0;
    while (str[i] != '\0') {
        i++;
    }
    return i;
}

//Function to concatenate the two strings
void concatenate(char *result, const char *str, const char *str2) {
    size_t i = 0;
    while (str[i] != '\0') {
        result[i] = str[i];
        ++i;
    }
    size_t k = 0;
    while (str2[k] != '\0') {
        result[i] = str2[k];
        k++;
        i++;
    }
    result[i] = '\0';
}

Here is an alternative approach, using pointer arithmetics:

//Function to concatenate the two strings
void concatenate(char *result, const char *str, const char *str2) {
    // copy the bytes from str, including the null terminator
    while ((*result = *str++) != '\0')
        result++;

    // copy the bytes from str2, including the null terminator
    while ((*result = *str2++) != '\0')
        result++;
}

Upvotes: 3

Fe2O3
Fe2O3

Reputation: 8354

Long worded explanations are usually difficult to follow because SO answers are typed (and edited and re-edited), and it is difficult to know what refers to which.

The very first comment response from @pmg tried to draw attention to some strange "index math". You may have imagined that if you 'skipped ahead two' there would magically be an ASCII space there to be printed... Wishes, eh?

Here's a "code dump" that improves on what you have written. By following it, line by line, you may see how it achieves the objective.

// notice these (small) functions just get the job done with short variable names
#include <stdio.h> // don't include headers you don't use

// a function DEFINED is a function DECLARED. no prototypes necessary
int string_length( char str[] ) {
    int i = 0;
    while( str[i] ) i++;
    return i;
}

void concatenate( char *dst, char *s1, char *s2 ) {
    while( ( *dst = *s1 ) != '\0') { dst++; s1++; }

    *dst++ = ' '; // padding space inserted

    while( ( *dst++ = *s2++ ) != '\0') { }
}

int main( void ) {
    char str1[] = "Hello there!";
    char str2[] = "How are you?";

    int length = string_length( str1 );
    printf( "'%s' length = %d\n", str1, length );

    char result[100]; // define variables when/where they are used
    concatenate( result, str1, str2 );
    printf( "%s\n", result );

    return 0;
}
'Hello there!' length = 12
Hello there! How are you?

If you're willing to move on from the length function, and start to return useful pointers from your functions, you can have your own versions of two standard library functions (without some of their more advanced features that you'll come to understand in time.)

#include <stdio.h>

char *string_copy( char *dst, char *s ) {
    for( char *p = dst; ( *p++ = *s++ ) != '\0'; ) { }
    return dst;
}

char *string_cat( char *dst, char *s ) {
    char *p = dst;
    while( *p ) p++;
    while( ( *p++ = *s++ ) != '\0') { }
    return dst;
}

int main( void ) {
    char result[100], str1[] = "Hello there!", str2[] = "How are you?";
    
    printf( "%s\n", string_cat( string_cat( string_copy( result, str1 ), " "), str2 ) );

    return 0;
}

The output is as expected.

Hello there! How are you?

The reason they are called functions is that they take one or more values, do something with them, and return something useful. (Think of trigonometry functions like sin that takes an angle and returns its y-axis offset on a unit-circle.

The functions and parameters in the last example have been nested to build up to the desired result.)

Upvotes: 1

Some programmer dude
Some programmer dude

Reputation: 409196

Because you skip two elements of the result array, it will look something like this after the second loop:

           +---+---+-----+---+---+---+---+---+---+---+----
Index    : | 0 | 1 | ... | 9 | 10| 11| 12| 13| 14| 15| ...
Character: | H | e | ... | r | e | ? | ? | H | o | w | ...
           +---+---+-----+---+---+---+---+---+---+---+----

At index 11 and 12 there will be two unknown characters.

If you want to add a space you need to explicitly add it. And I recommend you keep the same i variable as the result array index both when adding the space and in the second loop:

// Needs to be define here since it's reused later
unsigned i;

// Copy the first string
for (i = 0; str[i] != '\0'; ++i) {
    result[i] = str[i];
}

// The index i will be right after the last character of the first string
// Add the space there
result[i] = ' ';

// Increase i to the first position of the second string
++i;

// Then copy the second string
for (unsigned k = 0; str2[k] != '\0'; ++k, ++i) {
    result[i] = str2[k];
}

// Now add the string null terminator
result[i] = '\0';

After this result[11] will be a space, and directly following it (starting at result[12]) will be the second string.

Upvotes: 1

Th3Wh1t3Q
Th3Wh1t3Q

Reputation: 89

Problem lies in the fact that your result is empty (hence only 0s in it). When you skip indexes at line 38, you have a null terminator in your string that stops the reading from printf. You have to add manually a space if you do not want this comportment. Add a line after your first while result[i] = ' '; and you should have your expected result.

However, as it has been said, you do not have to skip 2 spaces with j. Only one suffices.

Upvotes: 1

Related Questions