Desafio função implode #21

Open
opened 2025-06-05 08:58:58 -03:00 by NRZCode · 9 comments

Fala Blau,

consegui escrever a função implode apenas com retorno tipo void e passando o vetor de char result como argumento.

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

void implode(char *result, char *glue, char **list, int count) {
    for (int i = 0; i < count; i++) {
        strcat(result, list[i]);
        if (i < count - 1) {
            strcat(result, glue);
        }
    }
}

int main(int argc, char **argv) {
    char result[BUFSIZ] = "";
    if (argc < 3) {
        fprintf(stderr, "Uso: %s DELIMITADOR STRINGS...\n", argv[0]);
        return 1;
    }
    implode(result, argv[1], argv + 2, argc - 2);
    printf("%s\n", result);

    return 0;
}

Eu gostaria de escrever a função implode retornando char *, mas não consegui um modo de fazê-lo.
A questão é que result seria uma variável de escopo local à função.

char *implode(char *glue, char **list, int count) {
    char result[BUFSIZ];
    ...
    return result;
}

main() {
    printf("%s\n", implode(argv[1], argv + 2, argc - 2));
    ...
}

Só definindo result como global ou tem alguma outra maneira?

Fala Blau, consegui escrever a função implode apenas com retorno tipo void e passando o vetor de char result como argumento. ```c #include <stdio.h> #include <stdlib.h> #include <string.h> void implode(char *result, char *glue, char **list, int count) { for (int i = 0; i < count; i++) { strcat(result, list[i]); if (i < count - 1) { strcat(result, glue); } } } int main(int argc, char **argv) { char result[BUFSIZ] = ""; if (argc < 3) { fprintf(stderr, "Uso: %s DELIMITADOR STRINGS...\n", argv[0]); return 1; } implode(result, argv[1], argv + 2, argc - 2); printf("%s\n", result); return 0; } ``` Eu gostaria de escrever a função implode retornando char *, mas não consegui um modo de fazê-lo. A questão é que result seria uma variável de escopo local à função. ```c char *implode(char *glue, char **list, int count) { char result[BUFSIZ]; ... return result; } main() { printf("%s\n", implode(argv[1], argv + 2, argc - 2)); ... } ``` Só definindo result como global ou tem alguma outra maneira?
Owner

@NRZCode wrote in #21 (comment):

Eu gostaria de escrever a função implode retornando char *, mas não consegui um modo de fazê-lo.
A questão é que result seria uma variável de escopo local à função.

O buffer de destino da nova string teria que ser um parâmetro:

char *implode(char *buf, char *glue, char **list, int count);

Se quiser testar o limite do buffer, inclui outro parâmetro:

char *implode(char *buf, int buf_size, char *glue, char **list, int count);

Isso deixa bem mais seguro.

Outra coisa, você pode testar se count é 0, por exemplo, e dar a possibilidade de utilizar vetores de strings terminados com NULL, como o argv e o envp.

Do mesmo modo, se *buf for NULL na chamada, o retorno poderia ser NULL e o resultado poderia ser impresso.

Editado:

É mais comum, seguro e compacto não receber uma contagem na função, exigindo que os vetores de strings terminem com NULL, porque essa é a condição típica de uso.

@NRZCode wrote in https://bolha.dev/blau_araujo/cblc/issues/21#issue-21: > Eu gostaria de escrever a função implode retornando char *, mas não consegui um modo de fazê-lo. > A questão é que result seria uma variável de escopo local à função. O buffer de destino da nova string teria que ser um parâmetro: ```c char *implode(char *buf, char *glue, char **list, int count); ``` Se quiser testar o limite do buffer, inclui outro parâmetro: ```c char *implode(char *buf, int buf_size, char *glue, char **list, int count); ``` Isso deixa bem mais seguro. Outra coisa, você pode testar se `count` é `0`, por exemplo, e dar a possibilidade de utilizar vetores de strings terminados com NULL, como o `argv` e o `envp`. Do mesmo modo, se `*buf` for `NULL` na chamada, o retorno poderia ser `NULL` e o resultado poderia ser impresso. ## Editado: É mais comum, seguro e compacto não receber uma contagem na função, exigindo que os vetores de strings terminem com `NULL`, porque essa é a condição típica de uso.
Owner

@NRZCode wrote in #21 (comment):

for (int i = 0; i < count; i++) {
strcat(result, list[i]);
if (i < count - 1) {
strcat(result, glue);
}
}

Mais um ponto... se result (ou o buffer de destino) já tiver um conteúdo, não seria legal verificar isso para colocar uma cola antes da primeira concatenação?

@NRZCode wrote in https://bolha.dev/blau_araujo/cblc/issues/21#issue-21: > for (int i = 0; i < count; i++) { > strcat(result, list[i]); > if (i < count - 1) { > strcat(result, glue); > } > } Mais um ponto... se `result` (ou o buffer de destino) já tiver um conteúdo, não seria legal verificar isso para colocar uma cola antes da primeira concatenação?
Author

@blau_araujo wrote in #21 (comment):

O buffer de destino da nova string teria que ser um parâmetro:

Pelo visto esse é o jeitão da linguagem C para strings, passar o destino como parâmetro e não retorná-la.

Isso não define o retorno da função do tipo void?

Esse char *implode(...) não faz muito sentido.

void implode(char *result, char *glue, char **list) {

@blau_araujo wrote in #21 (comment):

É mais comum, seguro e compacto não receber uma contagem na função, exigindo que os vetores de strings terminem com NULL, porque essa é a condição típica de uso.

O uso do count também visa a não concatenação da cola no último elemento da lista.

Atualizando a abordagem buscando o término com NULL sem o uso de count

for (int i = 0; list[i] != NULL; i++) {
    strcat(result, list[i]);
    strcat(result, glue);
}
result[strlen(result) - strlen(glue)] = '\0';
@blau_araujo wrote in https://bolha.dev/blau_araujo/cblc/issues/21#issuecomment-33: > O buffer de destino da nova string teria que ser um parâmetro: Pelo visto esse é o jeitão da linguagem C para strings, passar o destino como parâmetro e não retorná-la. Isso não define o retorno da função do tipo void? Esse `char *implode(...)` não faz muito sentido. ```c void implode(char *result, char *glue, char **list) { ``` @blau_araujo wrote in https://bolha.dev/blau_araujo/cblc/issues/21#issuecomment-33: > É mais comum, seguro e compacto não receber uma contagem na função, exigindo que os vetores de strings terminem com `NULL`, porque essa é a condição típica de uso. O uso do count também visa a não concatenação da cola no último elemento da lista. Atualizando a abordagem buscando o término com `NULL` sem o uso de count ```c for (int i = 0; list[i] != NULL; i++) { strcat(result, list[i]); strcat(result, glue); } result[strlen(result) - strlen(glue)] = '\0'; ```
Author

@blau_araujo wrote in #21 (comment):

se result (ou o buffer de destino) já tiver um conteúdo

Essa condicional antes do for faz isso.

if (*result)
    strcat(result, glue);
@blau_araujo wrote in https://bolha.dev/blau_araujo/cblc/issues/21#issuecomment-34: > se `result` (ou o buffer de destino) já tiver um conteúdo Essa condicional antes do for faz isso. ```c if (*result) strcat(result, glue); ```
Owner

@NRZCode wrote in #21 (comment):

Isso não define o retorno da função do tipo void?

Esse char *implode(...) não faz muito sentido.

Eu sugiro char * porque o retorno pode ser utilizado, por exemplo, chamando a função em um printf.

@NRZCode wrote in https://bolha.dev/blau_araujo/cblc/issues/21#issuecomment-35: > Isso não define o retorno da função do tipo void? > > Esse `char *implode(...)` não faz muito sentido. Eu sugiro `char *` porque o retorno pode ser utilizado, por exemplo, chamando a função em um `printf`.
Owner

@NRZCode wrote in #21 (comment):

O uso do count também visa a não concatenação da cola no último elemento da lista.

Pois é, tem que pensar em outra lógica... Ou implementar a função count também:

https://www.php.net/manual/en/function.count.php

;-)

@NRZCode wrote in https://bolha.dev/blau_araujo/cblc/issues/21#issuecomment-35: > O uso do count também visa a não concatenação da cola no último elemento da lista. Pois é, tem que pensar em outra lógica... Ou implementar a função `count` também: https://www.php.net/manual/en/function.count.php ;-)
Owner

@NRZCode wrote in #21 (comment):

consegui escrever a função implode apenas com retorno tipo void e passando o vetor de char result como argumento.

Você editou o código incial? O ideal é manter e postar as modificações nas respostas, senão a conversa fica sem sentido.

@NRZCode wrote in https://bolha.dev/blau_araujo/cblc/issues/21#issue-21: > consegui escrever a função implode apenas com retorno tipo void e passando o vetor de char result como argumento. Você editou o código incial? O ideal é manter e postar as modificações nas respostas, senão a conversa fica sem sentido.
Author

@blau_araujo wrote in #21 (comment):

@NRZCode wrote in #21 (comentário):

consegui escrever a função implode apenas com retorno tipo void e passando o vetor de char result como argumento.

Você editou o código incial? O ideal é manter e postar as modificações nas respostas, senão a conversa fica sem sentido.

Editei no mesmo momento da postagem.
Após o início das respostas não foi editada a postagem.

@blau_araujo wrote in https://bolha.dev/blau_araujo/cblc/issues/21#issuecomment-39: > @NRZCode wrote in #21 (comentário): > > > consegui escrever a função implode apenas com retorno tipo void e passando o vetor de char result como argumento. > > Você editou o código incial? O ideal é manter e postar as modificações nas respostas, senão a conversa fica sem sentido. Editei no mesmo momento da postagem. Após o início das respostas não foi editada a postagem.
Author

@blau_araujo wrote in #21 (comment):

Eu sugiro char * porque o retorno pode ser utilizado

Acabei de verificar que o retorno do buffer de destino vem das 2 formas, através do buffer passado nos argumentos e também no retorno da função.

Então char *implode(char *result, char *glue, char **list); traz versatilidade do uso

implode(dst, glue, list);
printf("%s\n", dst);
/*   ou    */
printf("%s\n", implode(dst, glue, list));
@blau_araujo wrote in https://bolha.dev/blau_araujo/cblc/issues/21#issuecomment-37: > Eu sugiro `char *` porque o retorno pode ser utilizado Acabei de verificar que o retorno do buffer de destino vem das 2 formas, através do buffer passado nos argumentos e também no retorno da função. Então `char *implode(char *result, char *glue, char **list);` traz versatilidade do uso ```c implode(dst, glue, list); printf("%s\n", dst); /* ou */ printf("%s\n", implode(dst, glue, list)); ```
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: blau_araujo/cblc#21
No description provided.