-1

As a homework I need to rewrite the string.h library, I have started with the strcat function but I am having trouble printing the **dest variable.

Here is the code:

#include <stdlib.h>
#include <stdio.h>
#ifndef MY_STRING_H
#define MY_STRING_H

int my_strlen(char *str){
    int count;
    for (count = 0; str[count] != '\0'; ++count);
    return count; 
}
 
void my_strcat(char **dest, const char *src){
    size_t srcSize = my_strlen((char *)src);
    size_t destSize = my_strlen((char *)dest);
    dest = realloc(dest ,(destSize + srcSize) * sizeof(char));
    int count;

    printf("%s \n", (char *) dest); //prints null here

    for (count = 0; dest[count] != '\0'; ++count); //throws segmentation error here
    for (int count2=0; src[count2] != '\0'; ++count2){
        *dest[count] = src[count2];
        count += 1;
    }
    *dest[count] += '\0';
}
 
int main (){
  char str[80] = "these strings";
  my_strcat ((char **) str,"are ");
  my_strcat ((char **) str,"concatenated.");
  printf("%s", str);
  return 0;
}

#endif // MY_STRING_H

I dont know how I can fix this please help me.

Bot Ellis
  • 108
  • 6
  • 1
    _"As a homework I need to rewrite the string.h library,"_ - that seems excessive for undergraduate-level homework - do you really and literally mean that you're expected to reimplement everything in that file, including `memcpy`, `memmove`, strerror`, etc? – Dai Nov 03 '22 at 02:32
  • @Dai well of course not everything sorry for the confusion but I only need to rewrite 4 functions in that library: `strcat` `strstr_match` `strspn` and `strtok` – Bot Ellis Nov 03 '22 at 02:36
  • Why is the first param of `my_strcat(char **dest,` a double pointer rather than a single pointer? – Avi Berger Nov 03 '22 at 02:36
  • @AviBerger unfortunately that is a boiler plate given by the school website so I have to work with it I guess? – Bot Ellis Nov 03 '22 at 02:36
  • 1
    ...I hope the reason the assignment asks you to reimplement `strtok` so that you know why you shouldn't use it :) – Dai Nov 03 '22 at 02:37
  • 2
    @BotEllis A `strcat` function using `char** dest` would be _nothing like_ C Std's `strcat` because it implies the responsibility of allocation is the callee's, not the caller's, which is the opposite of the real `strcat`, in which case I question the didactic value of this exercise... – Dai Nov 03 '22 at 02:39
  • @Dai I think the reason you are talking about is that it changes the pointed char. – Bot Ellis Nov 03 '22 at 02:39
  • 1
    Actually, I now see that the reason is that your my_strcat() is not a straight reimplementation of strcat(). It requires that the first parameter is a pointer to a pointer to malloc'ed memory & realloc's it to the right size. This means that your calls to it in main that pass str are invalid, as they do not meet the function's requirements. – Avi Berger Nov 03 '22 at 02:41
  • @BotEllis Not only that, but also because `strtok` isn't reentrant (because it mutates hidden state). There's a _lot_ of just-plain-_bad_ stuff in C. How can we forget `gets` is a thing? – Dai Nov 03 '22 at 02:41
  • You would need a char *malloced_ptr = malloc( some_number); in main and pass &malloced_ptr to my_strcat(). And copy some null terminated string into the buffer before passing it. Presuming I'm making the right guesses based on what you posted. – Avi Berger Nov 03 '22 at 02:44
  • BTW, your `my_strlen` should use `size_t count`, not `int` - and you might want to consider adding an assertion that `str != NULL` - and given the sheer size of 64-bit memory-space I'd also consider adding a sanity-check that asserts `count` never goes over something unreasonably large, like a couple of megabytes - otherwise a freak-accident-of-memory could cause your program to iterate over gigabytes of nonzero bytes of memory (and your `count` would overflow too). – Dai Nov 03 '22 at 02:47
  • `printf("%s", str);` <-- For trivial printing, consider using `puts` instead. – Dai Nov 03 '22 at 02:48
  • 1
    The original strcat is defined similar to `strcat(char *dest, const char *src)` which is rather different from your `my_strcat(char **dest, const char *src)`. Please explain why you want to do it differently. Also please bear in mind that **every** cast you have potentially masks a serious error. Your program should contain zero casts, and compile with [zero warnings](https://stackoverflow.com/questions/57842756/why-should-i-always-enable-compiler-warnings). If you are having trouble with writing a program this way and a cast seems like the only solution, stop and **ask a question**. – n. m. could be an AI Nov 03 '22 at 04:04
  • When you say *"boiler plate given by the school website"*, do you mean that you *have* to mantain the signatures `int my_strlen(char *str)` and `void my_strcat(char **dest, const char *src)` of those function? – Bob__ Nov 03 '22 at 09:20

1 Answers1

1

In my_strcat(), you used a char ** pointer while you transfer a char * pointer, maybe you can use (char *)dest.

(Also, since you have a my_strlen() function, you don't need a for loop to get the length of array.)

in this case, i tried to fix it like :

#include <stdlib.h>
#include <stdio.h>
#ifndef MY_STRING_H
#define MY_STRING_H

int my_strlen(char *str){
    int count;
    for (count = 0; str[count] != '\0'; ++count);
    return count; 
}
 
void my_strcat(char **dest, const char *src){
    size_t srcSize = my_strlen((char *)src);
    size_t destSize = my_strlen((char *)dest);
    dest = realloc(dest ,(srcSize+destSize) * sizeof(char));
    int count;
    int count2=0;
    printf("%s\n", (char *) dest); //prints null here
    for (count=0 ;((char *)dest)[count]!='\0'; ++count); //throws segmentation error here
    for (; src[count2] != '\0'; ++count2){
        ((char *)dest)[count] = src[count2];
        count += 1;
    }
    ((char *)dest)[count] += '\0';
}
 
int main (){
  char str[80] = "these strings";
  my_strcat ((char **) str,"are ");
  my_strcat ((char **) str,"concatenated.");
  printf("%s", str);
  return 0;
}

#endif // MY_STRING_H

By chance, i noticed that if replace printf("%s\n", (char *) dest) to printf("%s \n", (char *) dest), something wrong will happen. Amazing! I tried to read assembly code to found the difference between two code, and i find that for the first printf, it will be compilered into puts while the second will be compilered into printf with "%s \n" compilered into a string. I haven't know what happened now.

Then, suddenly, i think that we transfer a pointer str which point to data in stack, while it seems we need a pointer point to data in heap.

i tried some simple code:

#include <stdlib.h>
#include <stdio.h>
 
int main (){
  char str[80] = "these strings";
  printf("%lld\n", str);

  void * p = realloc(str ,100 * sizeof(char));
  printf("%lld", &((char *)p)[4]);
  return 0;
}

it works well. however, in:

#include <stdlib.h>
#include <stdio.h>
 
int main (){
  char str[80] = "these strings";
  printf("%lld\n", str);

  char str1[80] = "these strings";
  printf("%lld\n", str1);

  void * p = realloc(str ,100 * sizeof(char));
  printf("%lld", &((char *)p)[4]);
  return 0;
}

it can't work. then:

#include <stdlib.h>
#include <stdio.h>
 
int main (){
  char * str = (char *)malloc(80);
  str[0] = 'h'; str[1] = 'i'; str[2] = '\0';
  printf("%lld\n", str);

  char str1[80] = "these strings";
  printf("%lld\n", str1);

  void * p = realloc(str ,100 * sizeof(char));
  printf("%lld", &((char *)p)[4]);
  return 0;
}

it works well.

so, it seems you can't get str by this way, for the pointer transfered into realloc() should be alloced by malloc(), calloc() or realloc(). In another word, this pointer should point to data in heap. You can see this in realloc - cppreference. When i change the way we get str by malloc, it works well. You can try this.

At last, from the args of my_strcat(), i think maybe you should change the way you implement this function.

I haven't written C code for a long time, hope this can help you.

AshinZ
  • 136
  • 2