0

I'm new to pointers and I can already see how confusing they can be. I have tried to look this up in several threads and google but they don't quite return what I'm looking for maybe out of my inexperience.

I'm being passed an array of strings and I have to pass it again to another function however I'm extremely confused on how to do this and don't know what * or & to use or where.

My code:

#include <stdlib.h>
#include <stdio.h>

char    *ft_strcat(char *dest, char *src)
{
    unsigned int    c;
    unsigned int    count;

    count = 0;
    while (dest[count] != 0)
    {
        count++;
    }
    c = 0;
    while (src[c] != '\0')
    {
        dest[c + count] = src[c];
        c++;
    }
    dest[c + count] = 0;
    return (dest);
}

int size_str(char *str)
{
    int c;

    c = 0;
    while (str[c] != '\0')
    {
        c++;
    }
    return (c - 1);
}

int size_all(int size, char *strs[], char *sep)
{
    int i;
    int counter;

    i = 0;
    counter = 0;
    counter += size_str(sep) * (size - 1);
    while (i < size)
    {
        counter += size_str(strs[i]);
        i++;
    }
    return (counter);
}

char    *ft_strjoin(int size, char **strs, char *sep)
{
    int     i;
    char    *str;

    str = malloc(sizeof(char) * size_all(size, strs, sep));
    str = strs[0];
    i = 1;
    while (i < size)
    {
        str = ft_strcat(str, strs[i]);
    }
    return (str);
}

int main(void)
{
    char    *sep = "   ";
    char    a1[] = "Batata";
    char    a2[] = "frita";
    char    a3[] = "\'e";
    char    a4[] = "melhor";
    char    a5[] = "que";
    char    a6[] = "Banana";
    char    *strs[] = {a1, a2, a3, a4, a5, a6};
    char    *final = ft_strjoin(6, strs, sep);

    printf("%s", final);
}

I thought that size all would have to have an extra dereference operator on the declaration of the function and an reference operator when I call it, but this works just fine. Am I doing something wrong or am I just misunderstanding how pointers work? Don't I have to add an extra * each time I pass it?

Finally why doesn't while (src[c] != '\0') work?

7
  • str = malloc(sizeof(char) * size_all(size, strs, sep)); str = strs[0]; That doesn't make sense. The second statement overwrites the malloc result which means that memory is lost. Commented Jul 21, 2021 at 23:11
  • @kaylum you just fixed my incompetence, thanks tons! Commented Jul 21, 2021 at 23:18
  • Are you prohibited from using built-in functions like strlen()? Commented Jul 22, 2021 at 0:19
  • str = strs[0] should be strcpy(str, strs[0]) Commented Jul 22, 2021 at 0:20
  • size_str() shouldn't subtract 1. You're not counting the null byte in the loop, so you don't have to subtract it. Commented Jul 22, 2021 at 0:23

2 Answers 2

1

In size_str:

There's nothing wrong with while (src[c] != '\0'), but return (c - 1); is causing an off-by-one error with your string lengths. The NUL byte wasn't counted in the loop, there's no need to subtract 1.

In ft_strcat:

The first loop is repeating work that could be handled by a call to size_str.

In ft_strjoin:

str = malloc(sizeof(char) * sizeall(size, strs, sep)));

sizeof (char) is uneccessary, as it is always 1. You need an additional 1 byte added to the length passed to malloc to make room for the NUL byte in your final string.

Remember that pointers are values too. str = strs[0]; assigns the pointer held in strs[0] to the the variable str. It does not copy the contents of strs[0]. You are overwriting the value returned by malloc with a pointer to a different piece of memory.

Instead, given this set of functions, initialize the memory returned by malloc to be the empty string, by setting the first byte to NUL, and use ft_strcat to concatenate the first string.

There's no need to continually reassign the result of ft_strcat, as you are already altering str, and the return value will never change.

A complete example. One must not forget to free the resulting string when it is no longer needed.

#include <stdlib.h>
#include <stdio.h>

int size_str(char *str)
{
    int i = 0;

    while (str[i])
        i++;

    return i;
}

char *ft_strcat(char *dest, char *src)
{
    int i = 0,
        length = size_str(dest);

    do
        dest[length++] = src[i];
    while (src[i++]);

    return dest;
}

int size_all(int size, char **strs, char *sep)
{
    int total_length = size_str(sep) * (size - 1);

    for (int i = 0; i < size; i++)
        total_length += size_str(strs[i]);

    return total_length;
}

char *ft_strjoin(int size, char **strs, char *sep)
{
    char *result = malloc(1 + size_all(size, strs, sep));
    result[0] = '\0';

    ft_strcat(result, strs[0]);

    for (int i = 1; i < size; i++) {
        ft_strcat(result, sep);
        ft_strcat(result, strs[i]);
    }

    return result;
}

int main(void)
{
    char *sep = "   ";
    char a1[] = "Batata";
    char a2[] = "frita";
    char a3[] = "\'e";
    char a4[] = "melhor";
    char a5[] = "que";
    char a6[] = "Banana";
    char *strs[] = {a1, a2, a3, a4, a5, a6};
    char *final = ft_strjoin(6, strs, sep);

    printf("%s\n", final);

    free(final);
}

Output:

Batata   frita   'e   melhor   que   Banana
Sign up to request clarification or add additional context in comments.

4 Comments

"causing an off-by-one error with your string lengths" But when I run it it shows the full thing. as when I take the -1 off, what is happening?--- And In ft_strjoin I'm not casting to anything the other comment is. --- I don't quite understand what you mean by: There's no need to continually reassign the result of ft_strcat, as you are already altering str, and the return value will never change. I call it several times so it can add the next word to the previous string---Do I need to finish it off with a "\0"?
@MiguelP My mistake on the casting comment. Try testing your size_str function, in isolation, because with your implementation printf("%d\n", size_str("hello")); will show 4, not 5. If your program manages to work despite this, it is just luck, as your resulting memory will be too small, and writing past the end of a block of memory causes undefined behavior, wherein anything can happen.
So just fixing that fixes the memory issue?
Fixing that, and making sure to allocate one more byte for the resulting string's NUL terminating byte is enough to fix the memory issues. As for the second question: str never changes its address, it always points to the same base address of the block of memory you allocated, and ft_strcat alters this memory by writing more to the end of the string it contains each time. ft_strcat already places '\0' after each call, including the last call of course.
1

I have worked lately about this problematic, string joint. I noticed that you forgot to add an if condition where the size would be 0. Moreover, the while loop need an iteration, which means that it will give you an infinite loop.

You can find as follows some adjustment to your code:

int     i;
char    *str;
int     j;
int     k;

i = 0;
k = 0;
str = (char *)malloc(sizeof(char) * sizeall(size, strs, sep) + 1));
if (size == 0)
    return (0);
while (i < size)
{
    j = 0;
    while (strs[i][j])
        str[k++] = strs[i][j++];
    j = 0;
    if (i < size - 1)
        while (sep[j])
            str[k++] = sep[j++];
    i++;
}
str[k] = '\0';
return (str);

Feel free to ask me if there is something you did not understand, and good luck.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.