1. Limited time only! Sign up for a free 30min personal tutor trial with Chegg Tutors
    Dismiss Notice
Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

Homework Help: Implementing strcat without string.h in C

  1. Oct 27, 2014 #1
    Hi everyone. This is similar to my strcpy question previously. I tried to code but when I ran the code, a segmentation fault appears. I think this has something to do with my loop for the array but I have problems resolving it. May I have some help please? Thank you. My codes and the original question are below:

    Question: Implement the my_strcat(s1,s2) function to append a copy of string s2, including the terminating null character, to the end of string s1. The initial character of s2 overrides the null character at the end of s1. String s1 is returned.

    Use the function "char *my_strcat(char *s1, const char *s2);"

    Code (Text):

    #include <stdio.h>
       char *my_strcat(char *s1, const char *s2);
       int main(void)
       {
           char str1[40]={"goose"};
           char str2[40]={"berry"};
           char* s1;
           char* s2;
           char* type_berry;
     
          type_berry = my_strcat(s1, s2);
     
          printf("%s\n", *type_berry);
          return 0;
      }
     
      char *my_strcat(char *s1, const char *s2)
      {
          int i=0, j=0, count=0;
     
          while(s1[i] != '\0')
          {
              count = count + 1;
              i++;
          }
     
          i = count;
     
          while(s2[j]!= '\0')
          {
              s1[i]= s2[j];
              i++;
              j++;
          }
     
          return s1;
      }
     
    I think, after catting the 2 strings, I should get in C terms, gooseberry(\0). \0 is the last null char occupying the last box of the str, which is a char array.
     
  2. jcsd
  3. Oct 28, 2014 #2

    DrClaude

    User Avatar

    Staff: Mentor

    There are many things wrong with your code. I'll point out a few:
    What is the value of s1 and s2 at this point?

    Why do you have both count and i as variables?

    Do you guarantee that string s1 will end properly?
     
  4. Oct 28, 2014 #3
    Hi DrClaude. Oh dear. Hmm.. I need to think about my answers to the other questions, but I had:
    Code (Text):
    while(s1[i] != '\0')
          {
              count = count + 1;
              i++;
          }
    i = count;
    because I wanted to join str2[0] to str1[5]. However, when i reaches 4 for str1, s1[4] will be pointing at str1[4], but I need to replace str1[5], the NULL char with str2[0], thus I put "i = count" after the while loop since count would be 5 at that time.
     
  5. Oct 28, 2014 #4
    I am not very sure what are the values for s1 and s2, but when I return s1 from the my_strcat function, type_berry should bear the pointer s1 and thus when I print it out, it should give me gooseberry'\0'. This is my thought process (which I think may not be correct).. :(
     
  6. Oct 28, 2014 #5
    I tried to put:
    Code (Text):

    while(s2[j]!= '\0' && s1[i] != '\0'){
    {
        s1[i]= s2[j];
        i++;
        j++;
    }

      return s1;
    }
     
    but I got a seg. fault again. T.T
     
  7. Oct 28, 2014 #6

    DrClaude

    User Avatar

    Staff: Mentor

    I'll ask again. When the program reaches the line
    Code (C):

    type_berry = my_strcat(s1, s2);
     
    what are s1 and s2 pointing to?

    Before the while loop, both count and i are equal to 0. They are both incremented by 1 at each iteration. After the loop, i is replaced by count. You are basically counting the same thing twice.
     
  8. Oct 28, 2014 #7
    I think s1 is pointing to str1[9], while s2 is pointing to str2[5]. I don't think I am correct as the bottom-most while loop doesn't seem to be controlled correctly. ><

    I see. Hmm.. I was thinking when i=0, count = 1, since count would have incremented from 0 to 1 before i=0 increments to i=1 at i++. Am I wrong? ><
     
  9. Oct 28, 2014 #8

    Mark44

    Staff: Mentor

    DrClaude is asking about this code in your main() function. His question was "What are s1 and s2 pointing to?" Your reply above is not correct. Take a closer look at it.
     
  10. Oct 28, 2014 #9
    Oh my gosh!! I forgot to set where s1 and s2 are pointing to! T_T I'm so sorry. :( I will edit my code again and see what happens. My apologies DrClaude and Mark44.
     
  11. Oct 28, 2014 #10
    I have edited my codes and I shall re-post them here, which I hope will make referencing to my code easier. Thank you. Sorry. I can't believe I took so long to see my mistake. Sigh~

    Code (Text):

    #include <stdio.h>

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

    int main(void)
    {
        char str1[40]={"goose"};
        char str2[40]={"berry"};
        char* s1;
        char* s2;
        char* type_berry;

        s1 = &str1[0];
        s2 = &str2[0];

        type_berry = my_strcat(s1, s2);

        printf("%s\n", *type_berry);
        return 0;
    }

    char *my_strcat(char *s1, const char *s2)
    {
        int i=0, j=0, count=0;

        while(s1[i] != '\0')
        {
            count = count + 1;
            i++;
        }
        i = count;

       while(s2[j]!= '\0'&& s1[i]!= '\0')
       {
              s1[i]= s2[j];
              count++;
              j++;
       }
       s1[i] = '\0';
       return s1;
    }
     
     
  12. Oct 28, 2014 #11

    Mark44

    Staff: Mentor

    Without commenting on the validity of your code, there are some shortcuts you can take.

    You don't need braces { } when you initialize an array of char. You can do this:
    Code (Text):
    char str1[40] = "goose";
    If the array is of some other type than char, you still need the braces.

    Also, you can let the compiler figure out how much space to allocate for an initialized array. IOW, you can do this:
    Code (Text):
    char str1[] = "goose";
    Here the compiler will allocate enough space the characters of the string + a terminating null character. If you're going to be concatenating additional characters onto the string, then it's fine to specify how big the array should be. Since you're not doing anything to the str2 array, you could declare it similar to the above.

    You can declare and initialize a pointer in one statement, like so:
    Code (Text):
    char * s1 = str1;
    str1 is the same as &str1[0]. The name of an array evaluates to the address of the first element of the array.
     
  13. Oct 29, 2014 #12

    DrClaude

    User Avatar

    Staff: Mentor

    This part is broken.
     
  14. Oct 29, 2014 #13
    To Mark44:

    I see. I will note down your tips and tricks and perhaps use them for the final exams! Hopefully, I can save some time by writing 'less' code. Haha. :)

    To DrClaude:

    I see. But after staring at it for some time, I still can't write a correct code. May I have some hints please?
    My teacher went through the answer during class today but he used a combination of string functions (which were coded by him, i.e. not from string.h library) to solve the question. :O
     
  15. Oct 29, 2014 #14
    You've already made the necessary corrections.
    Your "my_strcat" that you originally posted is basically correct with two exceptions:
    1) Get rid of all references to "count". You aren't using that value.
    2) You need to terminate the s1 string with s1='\0';

    That first attempt was better than your second.
     
  16. Oct 29, 2014 #15

    DrClaude

    User Avatar

    Staff: Mentor

    Staring is not useful here. "Execute" the code with pen and paper and see what you get.

    If you compile the code in post #10, you get a warning, and the resulting executable ends with a segmentation fault, that means you didn't test it before posting.

    When you have a segmentation fault, you can use a debugger to help you. Compile the code with the -g flag, then run it using gdb:
    gdb ./a.out

    then at the prompt, type run. When the segmentation fault happens, the debugger will tell you which line was at fault.
     
  17. Oct 29, 2014 #16
    To DrClaude:

    This is the reason why I posted this here... I have vim, so I can compile the codes I write, and for this, I kept getting segmentation fault no matter what I did.

    However, after figuring out a little, I think I should remove the 2nd condition in the 2nd while loop, if not, the 2nd while loop will never run, as it will be while(true&&false). I will post my code separately together with my trace.

    Does the debugger work for all types of errors? This is because vim will give you the line number at which the error appears and one can look for the line and try to see what has happened. Does that count as a debugger?

    Thank you! :)

    To .Scott:

    Ah yes, I realise my mistake, but I feel that i=count should still remain because I have to concatenate str2[0] to str1[5], which for the latter is the '\0' character.

    Thank you! :)
     
  18. Oct 29, 2014 #17
    Trace for the first while loop:

    i 0 1 2 3 4 5
    count 1 2 3 4 5 X

    X-Terminates, since str1[5] is the NULL char.

    This is why I think i = count should still be there.

    However, for the 2nd while loop, I should have:

    Code (Text):

    while(s2[j]!= '\0')
          {
              s1[i]= s2[j];
              i++;
              j++;
          }
    s1[i] = '\0';
          return s1;
     
    I shall run the code tomorrow. Thanks to both for pointing out my mistakes and giving suggestions! :D
     
  19. Oct 29, 2014 #18

    Mark44

    Staff: Mentor

    I believe that the errors that vim notifies you of are syntax errors, errors you make in which you're using the language incorrectly. These are errors that the compiler can detect.

    The other type of error is a run-time error, which occurs when the program runs. The segmentation fault you're getting is a run-time error.
     
  20. Oct 29, 2014 #19
    I tried compiling my code erroneous code and I got this from gdb:

    May I know where do I see which line was at fault?

    Thanks! :)
     
  21. Oct 29, 2014 #20
    To Mark44: I see. :) Thanks!
     
  22. Oct 29, 2014 #21
    Code (Text):
    while(s2[j]!= '\0')
          {
              s1[i]= s2[j];
              i++;
              j++;
          }
    s1[i] = '\0';
          return s1;
    Hmm. I still have a segmentation fault when I ran my program. But this is weird, because when I trace the program, after the first while loop, the loop should have terminated, then, the above while loop starts, and it should end when s2 hits a NULL char, so logically, I shouldn't be exceeding the memory space allocated to me which produces a seg. fault.

    May I know if my thought processes are wrong?

    Thank you. :)
     
  23. Oct 29, 2014 #22

    Mark44

    Staff: Mentor

    When you say, "after the first while loop, the loop should have terminated," did it terminate? What you wrote suggests that you were expecting it to terminate, but for some reason it didn't.

    Use the debugger to single-step through your code. When you hit the seg fault, note which line caused it, and the values of the relevant variables.
     
  24. Oct 30, 2014 #23

    DrClaude

    User Avatar

    Staff: Mentor

    When the error happens in the code your wrote, gdb will tell you where immediately. The problem you are having now only creeps up in a system function, namely strlen. To know what your code was doing, use the command "where" in gdb after the segmentation fault:
    Code (Text):

    (gdb) where
    #0  0x00007fff8a434c00 in strlen ()
    #1  0x00007fff8a4405fc in __vfprintf ()
    #2  0x00007fff8a4818ab in vfprintf_l ()
    #3  0x00007fff8a4af007 in printf ()
    #4  0x0000000100000dec in main () at my_strcat.c:18
     
    so the error is in the printf on line 18.
     
  25. Oct 31, 2014 #24
    I know what my mistake was. I printed a string with a * instead of its address, which led to the segmentation fault.

    Thanks DrClaude for your tip on using gdb and Mark44 for your guidance in debugging my code. :)
     
  26. Nov 1, 2014 #25

    Mark44

    Staff: Mentor

    Yes
    Yes.
    Code (C):

    int main(void)
       {
           char str1[40]={"goose"};
           char str2[40]={"berry"};
           char* s1;
           char* s2;
           char* type_berry;

          type_berry = my_strcat(s1, s2);

          printf("%s\n", *type_berry);  //  << -- This line
          return 0;
      }
    I saw this before and thought it might be causing you trouble. What's happening is that the %s conversion specifier in printf is expecting the address of the first character of a string. *type_berry is the character 'g', but because of the %s, the value of the character (which is a number) is being interpreted as an address. That's your seg fault.
     
    Last edited: Nov 1, 2014
Share this great discussion with others via Reddit, Google+, Twitter, or Facebook

Have something to add?
Draft saved Draft deleted