Ir ao conteúdo

Posts recomendados

Postado

Crie uma função que retorna uma nova string igual à passada como parâmetro mas substituindo
todos os caracteres x pelo caractere y:
char * substituir(char *s, char x, char y);
Por exemplo, ao chamar substituir(palavra, ‘a’, ‘e’), sendo palavra lata, retorna lete.
Escreva a função main da seguinte forma, programando o que é solicitado nos comentários:
int main() {
char p[51], x, y, *nova;
fgets(p, 51, stdin);
if(p[strlen(p)-1] == '\n')
p[strlen(p)-1] = '\0';
scanf("%c %c", &x, &y);
//obter a nova string chamando a função substituir
//escrever na tela a string nova e a string original
//liberar memória da string nova
return 0;
}
Exemplo:
Input                               Output
um aviao                         um evieo um aviao
a e
 

  • Haha 1
Postado

Use o tal botão code como descrito no primeiro post do forum...

 

Veja a diferença

 

int main()
{
    char p[51], x, y, *nova;
    fgets(p, 51, stdin);
    if (p[strlen(p) - 1] == '\n') p[strlen(p) - 1] = '\0';
    scanf("%c %c", &x, &y);
    // obter a nova string chamando a função substituir
    // escrever na tela a string nova e a string original
    // liberar memória da string nova
    return 0;
}

 

Imagino que tenha recebido isso assim, e é uma pena...

 

    char p[51], x, y, *nova;

 

Não é muito esperto declarar mais de uma variável por linha. Nem todos seus programas vão ter meia dúzia de variáveis. E se perde tempo procurando pelas coisas. Tempo não se pode perder: digite uma única vez em separado.

 

nova é um ponteiro. Quando você declara assim está mascarando a realidade e isso também gera erro e dificulta o aprendizado. Em C você declara um nome, a variável, como sendo de um tipo.

 

nova é char*. Como nova é char* é óbvio que *nova é um char. É C. Mas está declarando o que? nova. Declare 

    char*                     nova = NULL; 

 

por exemplo. 

 

Mais ainda, está mais do que claro que nova será usado para receber o endereço da nova :D string, certo?

 

Então devia declarar 

 

char* nova = substituir(p, 'a', 'b');

 

por exemplo. É muito mais claro e seguro porque o ponteiro não fica uma linha sequer não inicializado, a causa mortis de boa parte dos programas de iniciantes e de muitos programas de profissionais que aprenderam assim :( errado.

 

    if (p[strlen(p) - 1] == '\n') p[strlen(p) - 1] = '\0';

 

Só aqui já tem duas chamadas a uma função, strlen().  E é bem provável que em substituir() se use outra chamada para determinar o tamanho da nova string a ser alocada.... 

 

E a presença de um '\n' em nada muda a lógica de substituir() :D Porque não mostrar a string resultante então com puts()  e chamar strlen() uma única vez se achar que precisa disso, dentro de substituir?

 

Qual a razão de escrever '\0' ao invés de 0? Seria mais fashion? Mais avançado? 0 é zero. Para que 4 símbolos e ficar procurando as p. das apóstrofes no teclado?

 

    scanf("%c %c", &x, &y);

 

Ao usar scanf() TESTE sempre o retorno. É ingênuo não testar e seguir em frente se não leu nada.

 

    fgets(p, 51, stdin);

 

fgets() retorna o que? char*. 

 

Como p não foi inicializado é claro que vai ficar com qualquer lixo se fgets() não ler nada. É ingênuo não testar se fgets() leu algo.

 

Quando se está começando a programar se tem a oportunidade de evitar esses hábitos ingênuos que levam a toda sorte de erros. Isso só vão fazer os iniciantes perderem tempo com coisas como o programa que passa direto pelo scanf(), coisa muito comum em todos os forums e plantões de dúvida de programação em C.

 

 

  • Curtir 2
Postado

@Igor Caldas Se não puder alterar a string original, vai precisar de uma auxiliar, não tinha me atentado a isso 🤪

O tamanho da string original já sabemos, mas se quiser alocar dinamicamente pra funcionar em todos os casos, pode fazer algo assim:

char* substituir(char* s, char x, char y)
{
    char* aux = (char*)malloc(strlen(s)+1);
    strcpy(aux, s);
    //printf("%s", aux);
    
    // Altere e retorne aux
}
  • Curtir 2
Postado
12 horas atrás, Lucca Rodrigues disse:
char* substituir(char* s, char x, char y)
{
    char* aux = (char*)malloc(strlen(s)+1);
    strcpy(aux, s);
    //printf("%s", aux);
    
    // Altere e retorne aux
}

 

Talvez chamar DUAS funções para fazer só isso seja um exagero.

 

Suponha uma string "Clube"

 

Claro, tem um zero no fim e para saber o tamanho strlen() vai ter que contar um por um até achar o zero, da esquerda para a direita.

 

Ao achar o zero vai criar a nova string com esse tamanho e voltar para outro loop onde vai comparar e trocar. 

 

Então deve ser possível seguir na memória contando até achar o zero nessa mesma função substituir() e quando achar saberá o tamanho. E aí pode ir voltando até o início trocando x por y. E quando chegar no início simplesmente retorna. E o início é bem conhecido: é o endereço s

 

Então não precisa de outras funções e algo assim deve servir:

 

char* substituir(char* antes, char de, char para)
{
    char E = 0; // vai pra frente ou pra tras?
    char* p = antes; // mais curto...
    char* str = NULL; // a string de retorno
    int tam = 0; // o tamanho
    while (1)
    { 
        switch (E)
        {
            case 0: // vai pra frente contando
                tam += 1;
                if (*p++ != 0) break;
                E         = 1;  // acabou
                str = malloc(tam);
                p--; // volta pro 0
                break;
            default: // volta comparando e trocando
                if (tam == 0) return str; // acabou
                tam -= 1;
                if (*p != de)
                    *(str + tam) = *p; // copia
                else
                    *(str + tam) = para; // troca
                p--;  // volta uma letra
                break;
        }   // switch()       
    };  // while()
    return NULL; // não vai passar aqui
}

 

claro que podia estar tudo dentro de um único if() e ter um label no inicio, mas assim é politicamente correto.

 

Veja o exemplo abaixo, sem esses while e switch artificiais

 

Um teste completo

 

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

char* substituir(char*,char,char);

int main(void)
{
    char     antes[51] = "x.x.x";
    char*    depois    = substituir(antes, '.', 'x');

    printf(
        "\
\n\
Original: \"%s\"\n\
Nova:     \"%s\"\n",
        antes, depois);
    free(depois);
    return 0;
}

char* substituir(char* antes, char de, char para)
{
    char E = 0; // vai pra frente ou pra tras?
    char* p = antes; // mais curto...
    char* str = NULL; // a string de retorno
    int tam = 0; // o tamanho
    while (1)
    { 
        switch (E)
        {
            case 0: // vai pra frente contando
                tam += 1;
                if (*p++ != 0) break;
                E         = 1;  // acabou
                str = malloc(tam);
                p--;
                break;
            default: // volta comparando e trocando
                if (tam == 0) return str; // acabou
                tam -= 1;
                if (*p != de)
                    *(str + tam) = *p;
                else
                    *(str + tam) = para;
                p--;  // volta uma letra
                break;
        }   // switch()       
    };  // while()
    return NULL; // não vai passar aqui
}

 

Que mostra

 

Original: "x.x.x"
Nova:     "xxxxx"

 

A versão curta e direta

 

char* substituir(char* antes, char de, char para)
{
    char  E   = 0;      // vai pra frente ou pra tras?
    char* p   = antes;  // mais curto...
    char* str = NULL;   // a string de retorno
    int   tam = 0;      // o tamanho

    // uma maquina de estados com DOIS estados
    FSM: if (E == 0)
    {
        tam += 1;
        if (*p++ != 0) goto FSM;
        E   = 1;  // acabou
        str = malloc(tam);
        p--;
    }
    else
    {
        if (tam == 0) return str;  // acabou
        tam -= 1;
        if (*p != de)
            *(str + tam) = *p;
        else
            *(str + tam) = para;
        p--;  // volta uma letra
    }
    goto FSM;
}

 

Claro, o resultado é o mesmo. E o código gerado também.

 

Algo ainda mais compacto

 

char* substituir(char* antes, char de, char para)
{
    char  E   = 0;      // vai pra frente ou pra tras?
    char* p   = antes;  // mais curto...
    char* str = NULL;   // a string de retorno
    int   tam = 0;      // o tamanho

// uma maquina de estados com DOIS estados
    FSM:if (E == 0)
    {
        tam += 1;
        if (*p++ == 0)
        {   E   = 1;  // acabou
            str = malloc(tam);
            p--;
        }
    }
    else
    {
        if (tam-- == 0) return str;  // acabou
        if (*p != de)
            *(str + tam) = *p;
        else
            *(str + tam) = para;
        p--;  // volta uma letra
    }
    goto FSM;
}

 

  • Curtir 1
  • Obrigado 1

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...