Ir ao conteúdo

C++ Atividade do curso em C++


Ir à solução Resolvido por arfneto,

Posts recomendados

Postado

Boa noite pessoal!

Consegui resolver a atividade proposta pelo professor, mas recebi o feedback de que eu poderia ser mais simplista.

Quais alterações eu poderia fazer para tornar o código mais simples?

 

Citação

Atividade: Utilizando o conceito de estruturas de dados do tipo fila, remova os nodos da lista que contém palavras duplicadas. E adicione comentários nas principais linhas de código adicionadas e responda: Cite um exemplo de aplicação do mundo real onde, na sua opinião, o código poderia ser aplicado e explique por qual motivo e como ele poderia resolver o problema. A saída do programa deve imprimir a lista final sem palavras duplicadas. 

 

 

LISTA

entrada.txt 

Uruguai
Itália
Itália
Uruguai
Alemanha
Brasil
Brasil
Inglaterra
Brasil
Alemanha
Argentina
Itália
Argentina
Alemanha
Brasil
França
Brasil
Itália
Espanha
Alemanha
França

 

 

 

 

 

CÓDIGO

#include <iostream>
#include <fstream>
#include <string>
#include <bits/stdc++.h>
using namespace std;
class Nodo
{
public:
    string data;
    string data2;
    Nodo *proximo;
};
void append(Nodo **head_ref, string new_data)
{
    // 1. aloca
    Nodo *new_Nodo = new Nodo();
    // usado no passo 5
    Nodo *last = *head_ref;
    // 2. preenche com dados
    new_Nodo->data = new_data;
    /* 3. o novo nodo será o último, então o proximo será NULL*/
    new_Nodo->proximo = NULL;
    /* 4. se a lista encadeada está vazia, faz o novo ser o início */
    if (*head_ref == NULL)
    {
        *head_ref = new_Nodo;
        return;
    }
    /* 5. ou percorra até o último nodo */
    while (last->proximo != NULL)
    {
        last = last->proximo;
    }
    /* 6. altera o proximo do útil nodo */
    last->proximo = new_Nodo;
    return;
}

// imprime o conteúdo da lista a partir do início recebido
void printList(Nodo *Nodo)
{
    while (Nodo != NULL)
    {
        cout << " " << Nodo->data;
        Nodo = Nodo->proximo;
    }
    cout << endl;
}

/*
Implemente aqui a funçao que identifica e remove palavras duplicadas
*/
void deletaNodo(Nodo *key) // pega um valor de ponteiro como chave
{

    Nodo *ptr;  //  ponteiro fixo
    Nodo *temp; // comparador
    Nodo *dup;  // valor duplicados
    ptr = key;  // ptr passa a ser "head", já que o ponteiro "key" recebe head como referência
    while (ptr != NULL && ptr->proximo != NULL)
    {
        temp = ptr;
        while (temp->proximo != NULL) // se houverem valores no nodo
        {
            if (ptr->data == temp->proximo->data) // se os valores comparados forem iguais
            {
                dup = temp->proximo;                    // dup recebe o valor duplicado
                temp->proximo = temp->proximo->proximo; // temp pula o valor duplicado
                delete (dup);                           // deleta o duplicado
            }
            else // não iguais
            {
                temp = temp->proximo; // temp pula para o proximo nodo e continua comparando
            }
        }
        //acabem os nodos para "temp->proximo"
        ptr = ptr->proximo; // fixo passa pro proximo nodo e começa outra comparação
    }
}
int main(int argc, char **argv)
{
    fstream arquivo;
    string palavra;
    if (argc < 2)
    {
        cout << "Faltou passar o arquivo como argumento!\n";
        return 1;
    }
    // arg 1 é um arquivo com as palavras a ser aberto
    arquivo.open(argv[1]);
    if (!arquivo.is_open())
    { // Se retornar algum erro:
        cout << "Erro ao abrir o arquivo!\n";
        return 1;
    }
    Nodo *head = NULL;
    // extrai todas as palavras e adiciona a lista:
    while (arquivo >> palavra)
    {
        append(&head, palavra);
    }
    cout << "ENTRADA:" << endl;
    printList(head);
    /* Aqui é chamada a função que filtra os dados duplicados */
    cout << endl;
    cout << "RESULTADO REMOVENDO DUPLICADOS:" << endl;
    deletaNodo(head); // passa o valor alocado no "head"
    printList(head);
    return 0;
}

 

  • Solução
Postado
7 horas atrás, Eclo disse:

Consegui resolver a atividade proposta pelo professor, mas recebi o feedback de que eu poderia ser mais simplista.

Quais alterações eu poderia fazer para tornar o código mais simples?

 

"mais simplista" é um critério difícil de entender, ao menos para mim. Não tenho ideia do que seria uma avaliação dessas, mas o que posso dizer grátis sobre o programa de um modo mais objetivo é que

  • é praticamente um programa C e não C++ e é um desperdício programar assim em C++
  • o programa não está bom
  • a estrutura de dados mal está presente e a implementação não é boa
class Nodo
{
   public:
    string data;
    string data2;
    Nodo*  proximo;
};

 

Trocar struct por class não cria um programa C++. E como tudo no código acima é public seria mais simples deixar struct mesmo.

 

Entenda: a diferença básica entre struct e class em C++ é que na struct tudo é public por padrão. Então é até engraçado usar class desse jeito. 

 

Sobre a fila

 

Está implementando a fila através de uma lista ligada e é o comum. Só que sequer tem uma classe fila. Uma fila é um container, como seria uma pilha, uma lista, um mapa, um conjunto... E seu programa nem tem isso. C++ é talvez a melhor linguagem para criar essas representações --- abstrações é o nome comum --- mas esse código nada fez a respeito.

 

No geral entenda que a fila é de nós. Não é de palavras. Nem de músicas ou livros como é presença comum nas listas de exercícios para iniciantes 😉 . Todos esses containers C++ chamados de coleções em java são de nós. Os nós é que tem os dados ou apontam para eles.

 

Quanto mais longe seu modelo ficar dessa realidade mais trabalho vai ter para criar o programa. E menos o código vai servir para usar em outros programas.

 

E está bem longe aqui. 

 

O simples é ter uma classe fila. A fila tem um começo e um fim. É uma fila. E tem operações. E um número de nós. O simples é isso. 

 

Não tem isso em seu programa e por isso por exemplo deletaNodo() recebe um ponteiro e tem mais 3 ponteiros dentro para a mesma coisa: nós.

 

E append recebe um argumento Nodo** que é um pesadelo de manutenção e tem mais 2 Nodo* dentro...

 

Use protótipos. É muito melhor. Veja a diferença no mesmo programa:

 

#include <iostream>
#include <fstream>
#include <string>
using namespace std;
class Nodo
{
   public:
    string data;
    string data2;
    Nodo*  proximo;
};

void append(Nodo** head_ref, string new_data);
void deletaNodo(Nodo* key);
void printList(Nodo* Nodo);

int main(int argc, char** argv)
{
    fstream arquivo;
    string  palavra;
    if (argc < 2)
    {
        cout << "Faltou passar o arquivo como argumento!\n";
        return 1;
    }
    // arg 1 é um arquivo com as palavras a ser aberto
    arquivo.open(argv[1]);
    if (!arquivo.is_open())
    {  // Se retornar algum erro:
        cout << "Erro ao abrir o arquivo!\n";
        return 1;
    }
    Nodo* head = NULL;
    // extrai todas as palavras e adiciona a lista:
    while (arquivo >> palavra) { append(&head, palavra); }
    cout << "ENTRADA:" << endl;
    printList(head);
    /* Aqui é chamada a função que filtra os dados
     * duplicados */
    cout << endl;
    cout << "RESULTADO REMOVENDO DUPLICADOS:" << endl;
    deletaNodo(head);  // passa o valor alocado no "head"
    printList(head);
    return 0;
}

void append(Nodo** head_ref, string new_data)
{
    // 1. aloca
    Nodo* new_Nodo = new Nodo();
    // usado no passo 5
    Nodo* last = *head_ref;
    // 2. preenche com dados
    new_Nodo->data = new_data;
    /* 3. o novo nodo será o último, então o proximo será
     * NULL*/
    new_Nodo->proximo = NULL;
    /* 4. se a lista encadeada está vazia, faz o novo ser o
     * início */
    if (*head_ref == NULL)
    {
        *head_ref = new_Nodo;
        return;
    }
    /* 5. ou percorra até o último nodo */
    while (last->proximo != NULL) { last = last->proximo; }
    /* 6. altera o proximo do útil nodo */
    last->proximo = new_Nodo;
    return;
}
/*
Implemente aqui a funçao que identifica e remove palavras
duplicadas
*/
void deletaNodo(
    Nodo* key)  // pega um valor de ponteiro como chave
{
    Nodo* ptr;   //  ponteiro fixo
    Nodo* temp;  // comparador
    Nodo* dup;   // valor duplicados
    ptr = key;  // ptr passa a ser "head", já que o ponteiro
                // "key" recebe head como referência
    while (ptr != NULL && ptr->proximo != NULL)
    {
        temp = ptr;
        while (temp->proximo !=
               NULL)  // se houverem valores no nodo
        {
            if (ptr->data ==
                temp->proximo
                    ->data)  // se os valores comparados
                             // forem iguais
            {
                dup = temp->proximo;  // dup recebe o valor
                                      // duplicado
                temp->proximo =
                    temp->proximo
                        ->proximo;  // temp pula o valor
                                    // duplicado
                delete (dup);       // deleta o duplicado
            }
            else  // não iguais
            {
                temp =
                    temp->proximo;  // temp pula para o
                                    // proximo nodo e
                                    // continua comparando
            }
        }
        // acabem os nodos para "temp->proximo"
        ptr = ptr->proximo;  // fixo passa pro proximo nodo
                             // e começa outra comparação
    }
}

// imprime o conteúdo da lista a partir do início recebido
void printList(Nodo* Nodo)
{
    while (Nodo != NULL)
    {
        cout << " " << Nodo->data;
        Nodo = Nodo->proximo;
    }
    cout << endl;
}

 

 

Porque é melhor?

 

Simples:

 

class Nodo
{
   public:
    string data;
    string data2;
    Nodo*  proximo;
};

void append(Nodo** head_ref, string new_data);
void deletaNodo(Nodo* key);
void printList(Nodo* Nodo);

 

esse trecho logo no começo já tem a estrutura e as funções pra você ler e lembrar delas. Tudo junto e não espalhado pelo código.

 

Sobre o código

 

Como eu disse, é um programa C apenas. 

  • Essas funções deveriam estar na classe
  • não use void
  • use nomes padrão para as operações
  • camelCase é algo de java. Em C++ raramente se usa

Remover palavras duplicadas é uma operação a executar em uma fila de palavras. O simples é ter o código de fila normal e ter uma função que recebe o endereço de uma fila e elimina as palavras duplicadas:

 

Algo assim
 

	int        remove_dup(Fila* fila);

 

Isso é o simples. Você lê um arquivo de palavras e cria uma fila e depois remove as palavras duplicadas.
 

Imagine isso ANTES de começar a programar:

 

	class Fila{};
 	Fila* cria_fila(const char* arquivo);
	int   mostra_fila(Fila*, const char*);
	int   remove_dup(Fila*);

 

Isso faz a vida simples. Seu programa seria

 

	Fila*   fila = cria_fila("palavras.txt");
	if (fila != nullptr) return -1;
	// ok criou a fila
	mostra_fila(fila,"lista original de palavras");
	remove_dup(fila);
	mostra_fila(fila,"lista sem palavras duplicadas");
	return 0;

 

Sugiro considerar 😉 

  • Amei 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...