Thread: Concatenate two strings.

  1. #1
    Registered User
    Join Date
    Apr 2011
    Posts
    23

    Concatenate two strings.

    I am trying to concatenate two strings together into a third string array, and allocating memory to store the third string and return the pointer to it.

    Here is what I have so far.

    Code:
    /* concatenate two strings and malloc() memory to store a third strings */
    
    #include <stdio.h>
    #include <stdlib.h>
    
    #define MAX 81
    
    
    char string1[MAX], string2[MAX];
    
    char link_array(char first[], char second[], int length);
    
    int main()
    {
        /* string input */
        puts("Enter your first line of text (maximum 80 characters): ");
        fgets(string1, sizeof(string1), stdin);
        
        puts("Enter your second line of text (maximum 80 characters): ");
        fgets(string2, sizeof(string2), stdin);
        
        printf("You entered %s", link_array(string1, string2, MAX));
        
        return 0;
    
    }
    
    char link_array(char first[], char second[], int length)
    {
        char *end1, *end2, c;
        int ctr;
        long totalsize;
        
        
        end1 = first;
        
        
        /* get memory address of last character in first string */
        for (ctr = 0; ctr < length; ctr++)
        {
            while(first[ctr] != '\0')
                  end1 = &first[ctr];
        }
        
        end2 = second;
        
        /* get memory address of last character in second string */
        for (ctr = 0; ctr < length; ctr++)
        {
            while(second[ctr] != '\0')
                end2 = &second[ctr];
        }
        
        /* malloc() the amount of memory needed to store string1 and string2 combined */
        
        totalsize = (&end1 - &first) + (&end2 - &second);    
        
        c = malloc(totalsize + 1);
        
        if (c == NULL)
        {
            puts("Memory allocation failed");
            exit(1);
        }
        
        /* combine the two strings using the memory addresses stored in end1 and end2 */
        /* can't figure this part out */
        
        return c;
    }

  2. #2
    Registered User
    Join Date
    Mar 2011
    Posts
    278
    Are you trying to avoid using strlen and strcat?

  3. #3
    Registered User
    Join Date
    Apr 2011
    Posts
    23
    I haven't learned those functions yet, I am working through the book Teach Yourself C in 21 days, and it takes a tutorial approach, this is an end of chapter exercise on working with basic string functions.

    edit:

    After looking at those functions, it would sure make this exercise a lot easier if the author had taught them during this chapter.

    Thanks for the heads up!
    Last edited by ModeSix; 04-26-2011 at 06:55 AM.

  4. #4
    Registered User
    Join Date
    Mar 2011
    Posts
    278
    Wow! That's a book I used 15 years ago when I crossed to the dark side (software) from the light (hardware). It's one of the few texts I could actually sit and read.

    Have you tried compiling yet?

  5. #5
    Registered User
    Join Date
    Apr 2011
    Posts
    23
    I haven't tried compiling it yet, as I hadn't written the concatenate function yet.

    I'm writing it using Mac OSX XCode for my editor and it's showing warnings on a few lines, I'll compile it and post the results here. Should be interesting.

    Here is the output I get from cc main.c

    Code:
    main.c: In function ‘main’:
    main.c:22: warning: format ‘%s’ expects type ‘char *’, but argument 2 has type ‘int’
    main.c: In function ‘link_array’:
    main.c:58: warning: assignment makes integer from pointer without a cast
    main.c:60: warning: comparison between pointer and integer
    All warnings which I assume are related to type declarations, no outright compile errors though.

    Yeah it is a very readable book, I also own the The C Programming Language (second edition), which doesn't take a tutorial approach, so got Teach Yourself C in 21 Days to supplement the very obviously missing learning curve in the aforementioned book.
    Last edited by ModeSix; 04-26-2011 at 07:09 AM.

  6. #6
    Registered User
    Join Date
    Mar 2011
    Posts
    278
    Never ignore warnings. You might be trying to do things that are technically "legal" but are not going to yield the results you want.

    Code:
        for (ctr = 0; ctr < length; ctr++)
        {
            while(first[ctr] != '\0')
                  end1 = &first[ctr];
        }
    In the while loop you aren't incrementing ctr so it'll never exit (infinite loop).

    Without changing your overall strategy, this simpler code might do what you want:
    Code:
        ctr = 0;
        while(first[ctr] != '\0') {
            end1 = &first[ctr];
            ctr++;
        }

  7. #7
    Registered User
    Join Date
    Apr 2011
    Posts
    23
    Quote Originally Posted by mike65535 View Post
    Never ignore warnings. You might be trying to do things that are technically "legal" but are not going to yield the results you want.

    Code:
        for (ctr = 0; ctr < length; ctr++)
        {
            while(first[ctr] != '\0')
                  end1 = &first[ctr];
        }
    In the while loop you aren't incrementing ctr so it'll never exit (infinite loop).

    Without changing your overall strategy, this simpler code might do what you want:
    Code:
        ctr = 0;
        while(first[ctr] != '\0') {
            end1 = &first[ctr];
            ctr++;
        }
    Amazingly, that was exactly what was happening, after inputting the two strings, it would just do nothing, which I assume was a direct result of the infinite loop you spoke of.

    I am probably going to rewrite this using the strlen() and strcat() functions you mentioned. There is no point in doing this the long and tedious way when a standard library method is available to do some of the raw calculations for me.

  8. #8
    Registered User
    Join Date
    Mar 2011
    Posts
    278
    There is no point in doing this the long and tedious way when a standard library method is available
    Well, I wouldn't say that. One can learn a lot by trying to implement what seems to be a simple function! But, if you've bigger fish to fry...

  9. #9
    Registered User
    Join Date
    Apr 2011
    Posts
    23
    Quote Originally Posted by mike65535 View Post
    Well, I wouldn't say that. One can learn a lot by trying to implement what seems to be a simple function! But, if you've bigger fish to fry...
    I think I will attempt to do it both ways, because doing it the long way probably will teach me something I need to know down the road for another purpose.

    Now onto my next question.

    When calling the malloc() function, I am receiving a warning as follows:
    Code:
    main.c: In function ‘link_array’:
    main.c:58: warning: assignment makes integer from pointer without a cast
    main.c:60: warning: comparison between pointer and integer
    I am making sure that malloc() is actually working and isn't returning a NULL value.

    Code:
    totalsize = (&end1 - &first) + (&end2 - &second);    
    
    c = malloc(totalsize + 1);
    
    if (c == NULL)
    {
        puts("Memory allocation failed");
        exit(1);
    }
    What am I doing wrong here?

    Would (if c == '\0') be more appropriate for this?

    I'm also getting a memory allocation failure on this.
    Last edited by ModeSix; 04-26-2011 at 07:47 AM.

  10. #10
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    c is of type char. It needs to be a pointer to char. char is technically an integral type, hence the wording of the error message (although that is compiler dependent).

    link_array() would also need to return a pointer.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  11. #11
    Registered User
    Join Date
    Apr 2011
    Posts
    23
    I've refined the function and it's not producing errors, as well as allocating memory correctly. Now to concatenate the two strings together.

    Code:
    char link_array(char first[], char second[], int length)
    {
        
         
         char *end1, *end2, *c;
         int ctr;
         long totalsize;
         
         end1 = first;
         
         /* get memory address of last character in first string */
         ctr = 0;
         while(first[ctr] != '\0') {
             end1 = &first[ctr];
             ctr++;
         }
         
         end2 = second;
         
         /* get memory address of last character in second string */
         ctr = 0;
         while(second[ctr] != '\0') {
             end2 = &second[ctr];
             ctr++;
         }
         
         /* malloc() the amount of memory needed to store string1 and string2 combined */
         
         totalsize = (end1 - first) + (end2 - second);    
            
         c = malloc(totalsize + 1);
         
         if (c == NULL)
         {
         puts("Memory allocation failed");
         exit(1);
         }
         
        printf("You allocated %lu bytes of memory to store the string\n", totalsize + 1);
        
         /* combine the two strings using the memory addresses stored in end1 and end2 
         can't figure this part out */
         
         return *c;
        
    }
    Last edited by ModeSix; 04-26-2011 at 07:57 AM.

  12. #12
    Registered User
    Join Date
    Mar 2011
    Posts
    278
    What am I doing wrong here?
    I don't want to spoon feed you since it appears you want to learn some stuff "the hard way" (congrats on that). Besides there are probably dozens of ways to do this, each with a dozen variations...

    link_array itself (based on its prototype) returns a char, but you really want a string for the result, right? So you could return a char*, or to pass in a third (destination) char array.

    Like this
    Code:
    char link_array(char destination[], char first[], char second[], int length)
    Of course, now the parameter length gets even more problematic than it was since it's the length of which array? You had it as a sort of, what we call, "magic number" (generally bad philosophically) fixed at MAX. But if you concatenate two MAX strings you get 2 times MAX...

    You might also want to break up your link_array function some.
    Create a simple (no need for it to be robust if you're just learning) my_calc_string_length function and pass it one char array at a time and let it find the length and pass it back as a return value. You could then use the final value of ctr (from your loop) as the length, rather than trying to do math on the addresses using the pointers (unless you really WANT to do that...)

  13. #13
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by ModeSix View Post
    I am probably going to rewrite this using the strlen() and strcat() functions you mentioned. There is no point in doing this the long and tedious way when a standard library method is available to do some of the raw calculations for me.
    I wouldn't pack it in just yet... Programming is, by it's nature, a "long and tedious way" of doing things. You need to build patience to do the work and you need analytical skills to understand the task... these do not always come easily so you need to work on them as much as you work on the actual code.

    One of the big mistakes I see programmers making all the time is trying to write one huge function that does everything... but if you think in smaller blobs, sometimes the result is better.

    It's often helpful is to sit down and look at what you have to do and make lists of the sub-functions that need to be performed... in the example of concactenating two strings and placing them in a third... You need to know the length of each string, you need to allocate memory for the new string, you need to copy each string starting at an offset in the new string and you need to inform the calling function of the new string's address...

    Now from this list, which things do you need to do more than once? Each of those things becomes a sub-function....

    For example, you can write strlen in three lines...
    Code:
    int MyStrLen(char* str)
     { char* ptr = str;                         // don't want to disturb the input pointer.
        while(*ptr++);                           // find the null
        return (int) --ptr - str; }             // return the length
    You can then call this function from your concact function to get the length of each string to use in allocating memory.
    Code:
    char *dst = NULL;                                // final string
    
    dst = malloc(MyStrlen(strA) + MyStrlen(StrB) + 1);
    Once you refine it down to the point of a complete understanding, the coding task becomes much simpler.

    So my advice would be... "Work in smaller blobs"....
    Last edited by CommonTater; 04-26-2011 at 08:14 AM.

  14. #14
    Registered User
    Join Date
    Apr 2011
    Posts
    23
    Quote Originally Posted by mike65535 View Post
    I don't want to spoon feed you since it appears you want to learn some stuff "the hard way" (congrats on that). Besides there are probably dozens of ways to do this, each with a dozen variations...

    link_array itself (based on its prototype) returns a char, but you really want a string for the result, right? So you could return a char*, or to pass in a third (destination) char array.

    Like this
    Code:
    char link_array(char destination[], char first[], char second[], int length)
    Of course, now the parameter length gets even more problematic than it was since it's the length of which array? You had it as a sort of, what we call, "magic number" (generally bad philosophically) fixed at MAX. But if you concatenate two MAX strings you get 2 times MAX...

    You might also want to break up your link_array function some.
    Create a simple (no need for it to be robust if you're just learning) my_calc_string_length function and pass it one char array at a time and let it find the length and pass it back as a return value. You could then use the final value of ctr (from your loop) as the length, rather than trying to do math on the addresses using the pointers (unless you really WANT to do that...)
    I've managed to get the allocation function and length calculations working properly, and yes I should probably break this into other functions, which I will do shortly.

    I am going to have to figure this out. Should be interesting.

    This is a lot of new ground for me in a single chapter. I've gone from a basic introduction to pointers to this. Whee.

    Thank you for having patience.

    edit:
    I've also not used the length variable within the function yet, so I can likely scrap it altogether as it's not being used.
    Last edited by ModeSix; 04-26-2011 at 08:07 AM.

  15. #15
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    When I say link_array needs to return a pointer, I mean
    Code:
    char *link_array(<your arguments>)
    NOT
    Code:
        return *c;
    at the end of the function.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. concatenate
    By violatro in forum C Programming
    Replies: 16
    Last Post: 06-04-2010, 09:22 AM
  2. Replies: 2
    Last Post: 03-30-2009, 12:25 AM
  3. concatenate two strings! K&R problem
    By karanmitra in forum Linux Programming
    Replies: 2
    Last Post: 08-09-2005, 10:44 AM
  4. Concatenate chars and std::strings.
    By Hulag in forum C++ Programming
    Replies: 3
    Last Post: 06-29-2005, 08:20 AM
  5. concatenate
    By port in forum C Programming
    Replies: 1
    Last Post: 11-25-2002, 09:53 PM