First tell me how much memory you will need. Then allocate the memory and then begin to concatenate. To not have to use ft_strlen
twice in each string, you can use a cache.
Furthermore, in% with_of% you used malloc
instead of sizeof(char *)
, so you would end up allocating much more memory than necessary. In fact, since sizeof(char)
is 1 always, you do not need to use it in this case.
Also, your sizeof(char)
is very strange. Placing the contents of a string in itself is not something that makes much sense there.
And you're allocating the string within ft_strcpy(newString[aux2],newString[aux2]);
(and nothing to free it). Since you only want to produce a single string at the end, allocating within while
will not work.
First of all, we need while
and implementation of #include <stdlib.h>
and ft_strcpy
:
char *ft_strcpy(char *dst, const char *src) {
int i = -1;
do {
i++;
dst[i] = src[i];
} while (src[i]);
return dst;
}
int ft_strlen(const char *src) {
int i = 0;
while (src[i]) i++;
return i;
}
Here is your reviewed code:
char *ft_concat_params(int argc, char **argv) {
// Cache com os tamanhos das strings.
int *cache = (int *) malloc(argc * sizeof(int));
// Conta o tamanho das strings.
int count = 1; // 1 = espaço do terminador nulo.
for (int i = 0; i < argc; i++) {
cache[i] = ft_strlen(argv[i]);
count += cache[i];
}
// Cria a nova string que será retornada.
char *newString = (char *) malloc(count);
// Copia as strings para o newString.
// Usa aux para percorrer o espaço de memória de newString.
char *aux = newString;
for (int i = 0; i < argc; i++) {
ft_strcpy(aux, argv[i]);
aux = &(aux[cache[i]]);
}
// Adiciona o terminador nulo.
aux[0] = 0;
// Não precisamos mais da cache.
free(cache);
// Terminamos.
return newString;
}
To test this code (along with ft_strlen
), we use this:
int main(void) {
const char *strings1[] = {"banana", "pera", "uva"};
char *a = ft_concat_params(3, strings1);
printf("[%s] - %d\n", a, ft_strlen(a));
free(a);
const char *strings2[] = {"", "teste", "", "mais", "", "perigoso", ""};
char *b = ft_concat_params(7, strings2);
printf(["%s] - %d\n", b, ft_strlen(b));
free(b);
const char *strings3[] = {"", "", ""};
char *c = ft_concat_params(3, strings3);
printf("[%s] - %d\n", c, ft_strlen(c));
free(c);
const char *strings4[] = {};
char *d = ft_concat_params(0, strings4);
printf("[%s] - %d\n", d, ft_strlen(d));
free(d);
return 0;
}
Here's the output:
[bananaperauva] - 13
[testemaisperigoso] - 17
[] - 0
[] - 0
These last two were to be empty, really. These are special case tests.
See here working on ideone.
It is possible to implement this without using the cache and nor use #include <stdio.h>
more than once, if we do not use ft_strlen
by changing the piece that copies the strings to this:
// Copia as strings para o newString.
// Usa aux para percorrer o espaço de memória de newString.
char *aux = newString;
for (int i = 0; i < argc; i++) {
for (int j = 0; argv[i][j]; j++, aux++) {
aux[0] = argv[i][j];
}
}
The output produced is the same.
See here working on ideone.
To know which approach would perform best, it would require very complex tests, and this also depends on how ft_strcpy
is implemented. Other, very different approaches are certainly possible.