Ir ao conteúdo
  • Cadastre-se

C++ Dobrar o tamanho do vetor a cada redimensionamento em c++


fevilela

Posts recomendados

Pessoal eu escrevi um codigo, esse codigo tem que cadastrar o nome, marca e descrição e tem que dobrar o tamanho do vetor a cada redimensionamento. Porém quando eu cadastro um novo produto e coloco para mudar a marca ele faz tranquilo porém ocorre uma falha de segmentação. Alguém poderia me ajudar com isso? O código é esse:

#include <iostream>
#include <vector> 
using namespace std;

struct produto {
    string nome;
    string marca;
    string descricao;
    produto();
};

produto::produto() {
    nome.clear();
    marca.clear();
    descricao.clear();
}

class portfolio {
    private:
        // *** AVISO: Não altere os atributos privados da classe *** 
        produto* listaDeProdutos;
        int quantidadeDeProdutos;
        int capacidadeMaxima;
    public:
        portfolio(int capacidade);
        ~portfolio();
        void inserirNovoProduto(const produto& umProduto);
        bool buscarProduto(const string& nome, produto& umProduto);
        void redimensionarCapacidade();
        friend void simularMudancaDeMarca(portfolio umPortfolio, string marcaAntiga, string novaMarca);
};

portfolio::portfolio(int capacidade) {
    quantidadeDeProdutos = 0;
    capacidadeMaxima = capacidade;
    listaDeProdutos = new produto[capacidadeMaxima];
}

portfolio::~portfolio() {
    delete [] listaDeProdutos;
}

void portfolio::inserirNovoProduto(const produto& umProduto) {
    if (quantidadeDeProdutos == capacidadeMaxima) { // vetor cheio, precisa redimensionar
        redimensionarCapacidade();
    }
    listaDeProdutos[quantidadeDeProdutos] = umProduto;
    quantidadeDeProdutos++;
}

bool portfolio::buscarProduto(const string& nomeParaBusca, produto& umProduto) {
    int posicaoAtual = 0;

    while (posicaoAtual < quantidadeDeProdutos and 
           listaDeProdutos[posicaoAtual].nome != nomeParaBusca) 
        posicaoAtual++;

    // se posicaoAtual não for menor que quantidade de produtos, é porque não encontrou
    if (posicaoAtual < quantidadeDeProdutos) {
        umProduto = listaDeProdutos[posicaoAtual];
        return true;
    }

    return false;
}

void portfolio::redimensionarCapacidade() {
//#warning implemente este metodo!
	std::vector<produto> listaDeProdutos;
	produto umProduto;
	listaDeProdutos.erase(listaDeProdutos.begin()+2);
	listaDeProdutos.push_back(umProduto);

}

void simularMudancaDeMarca(portfolio umPortfolio, string marcaAntiga, string novaMarca) {
    // *** AVISO: Não altere esta função *** 
    for (int i = 0; i < umPortfolio.quantidadeDeProdutos; i++) {
        if (umPortfolio.listaDeProdutos[i].marca == marcaAntiga) 
            cout << umPortfolio.listaDeProdutos[i].nome << " " << novaMarca << endl;
    }
    cout << endl;
}


int main() {
    // *** AVISO: Não altere a função principal, o main() *** 
    int capacidadeInicial;

    cout << "Produtos - Aplicativo para Controlar Portfolio\n" 
         << "Entre com capacidade máxima inicial: ";
    cin >> capacidadeInicial;

    portfolio meuPortfolio(capacidadeInicial);

    cout << "Portfolio - Escolha a Opção:\n"
         << "i - inserir novo produto\n"
         << "b - buscar por um dado produto a partir do nome\n"
         << "m - simular mudança de marca\n"
         << "s - para sair do programa" << endl;

    char opcaoDoMenu;
    produto umProduto;
    string nome;
    string marcaAntiga, marcaNova;

    cin >> opcaoDoMenu;

    while (opcaoDoMenu != 's') {
        switch(opcaoDoMenu) {
            case 'i' : 
                cout << "Entre com dados do produto (nome, marca, descrição):" << endl;
                cin >> umProduto.nome 
                    >> umProduto.marca
                    >> umProduto.descricao;
                meuPortfolio.inserirNovoProduto(umProduto);
                break;

            case 'b' :
                cout << "Entre com nome do produto para busca: ";
                cin >> nome;
                
                if (meuPortfolio.buscarProduto(nome, umProduto)) 
                    cout << umProduto.nome << " "
                         << umProduto.marca << " "
                         << umProduto.descricao << endl << endl;
                else 
                    cout << "Produto não encontrado!" << endl << endl;
                break;

            case 'm' : 
                cout << "Entre com marca antiga e atual: ";
                cin >> marcaAntiga >> marcaNova;
                simularMudancaDeMarca(meuPortfolio,marcaAntiga,marcaNova);
                break;

            case 's' : // não faz nada, espera retorno ao while para sair 
                break;

            default:
                cout << "Opção inválida!" << endl;
                break;

        }
        cout << "Portfolio - Escolha a Opção:\n"
             << "i - inserir novo produto\n"
             << "b - buscar por um dado produto a partir do nome\n"
             << "m - simular mudança de marca\n"
             << "s - para sair do programa" << endl;
        cin >> opcaoDoMenu;
    }

    return 0;
}

 

Link para o comentário
Compartilhar em outros sites

Vai ser mais prático se você usar std::vector pra listaDeProdutos:

 

// class portfolio

std::vector<produto> listaDeProdutos;

 

Agora você não vai mais precisar de quantidadeDeProdutos, porque basta checar o tamanho de listaDeProdutos em tempo real:

 

quantidade = listaDeProdutos.std::vector<produto>::size();

 

E também não vai precisar de capacidadeMaxima porque o std::vector cuida disso pra você. Pra adicionar um novo produto sem precisar reajustar a lista pessoalmente, você pode usar o push_back() de std::vector:

 

// portfolio::inserirNovoProduto()

listaDeProdutos.std::vector<produto>::push_back(umProduto);

 

Também não vai mais precisar de portfolio::redimensionarCapacidade().

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

12 horas atrás, V!OLADOR disse:

Vai ser mais prático se você usar std::vector pra listaDeProdutos

 

Sim, @V!OLADOR! E talvez mais simples ainda usar <list> e declarar
 

    list<produto> lista_de_produtos;

 

Mas note o aviso

 

class portfolio
{
   private:
    // *** AVISO: Não altere os atributos privados da classe ***
    produto* listaDeProdutos;
    int      quantidadeDeProdutos;
    int      capacidadeMaxima;

 

Esse é o objetivo: implementar listaDeProdutos como produto* e incrementar o tamanho em escala quadrática. E aí está o tamanho na classe.

 

@fevilela Pode postar o enunciado? O que você pode mudar nisso? No geral não é assim que se costuma escrever isso. Há problemas em várias partes. C++ não é C e o programa parece perdido no caminho.

 

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

@arfneto Claro, esse é o enunciado:

Um sistema em desenvolvimento permite controlar o portfólio de um escritório de publicidade. No momento, ele só permite a inserção e busca de produtos. Falta implementar, inclusive, o redimensionamento do vetor de produtos. O redimensionamento ocorrerá de acordo com a estratégia que foi sorteada para você. Além disso, foi desenvolvida uma função externa à classe para simular a mudança de marca de alguns produtos. A função já está testada e não pode ser alterada. Entretanto, o uso dessa função gera falha de segmentação. A interface do programa (a função main()) também não pode ser alterada, bem como os atributos privados da classe. Sua tarefa é corrigir o problema com essa função externa, bem como implementar o redimensionamento do vetor de produtos. 

Link para o comentário
Compartilhar em outros sites

@fevilela mas e o código como foi recebido? Imaginei que estaria como parte do enunciado.

 

47 minutos atrás, fevilela disse:

O redimensionamento ocorrerá de acordo com a estratégia que foi sorteada para você

 

Imagino que o sorteio determinou que deve dobrar de tamanho a cada redimensionamento :)

 

O programa não está assim bom :(. O instrutor nem se decidiu sobre usar warning

 

void portfolio::redimensionarCapacidade()
{
    //#warning implemente este metodo!

 

ou AVISO 
 

void simularMudancaDeMarca(
    portfolio umPortfolio, string marcaAntiga, string novaMarca)
{
    // *** AVISO: Não altere esta função ***

 

:) 

 

Essa não é a maneira recomendada de programar em C++ desde uns 15 anos atrás.

 

Por exemplo, não precisa de um construtor para produto.
 

strings são classes e assim tem seus próprios construtores, e isso 
 

produto::produto()
{
    nome.clear();
    marca.clear();
    descricao.clear();
}

 praticamente não tem sentido

 

 

  • main() deve ser a primeira função de seu programa, se possível em um arquivo separado.
     
  • não entendo essas linhas
    {
        //#warning implemente este metodo!
        std::vector<produto> listaDeProdutos;
        produto              umProduto;
        listaDeProdutos.erase(listaDeProdutos.begin() + 2);
        listaDeProdutos.push_back(umProduto);
    }


    listaDeProdutos é int*, declarada em portfolio...

    produto* listaDeProdutos;

 

 

Então não é surpresa que seu programa cancele aí...

 

O que quer fazer com erase(), iteradores e push_back()?

Que é esse umProduto, que sequer foi inicializado?

 

Não precisa fazer nada muito especial nesse caso. O programa sequer permite.
 

O que seria o simples?

 

Algo assim
 

void portfolio::redimensionarCapacidade()
{
    //#warning implemente este metodo!
    int n = quantidadeDeProdutos + quantidadeDeProdutos;
    cout << "Redimensionando: de " << quantidadeDeProdutos << " para "
         << n << "\n";
    produto* doisX = new produto[n];
    cout << "criada nova area\n";
    for (int i = 0; i < quantidadeDeProdutos; i += 1)
        doisX[i] = listaDeProdutos[i];
    cout << "copiados produtos\n";
    delete[] listaDeProdutos;
    listaDeProdutos = doisX;
    capacidadeMaxima = n;
}

 

E depois de testar, sem os cout, podia ser:
 

void portfolio::redimensionarCapacidade()
{
    int n = quantidadeDeProdutos + quantidadeDeProdutos;
    produto* doisX = new produto[n]; // nova area com 2X o tamanho
    for (int i = 0; i < quantidadeDeProdutos; i += 1) doisX[i] = listaDeProdutos[i];
    // copiados os produtos apaga a lista antiga
    delete[] listaDeProdutos;
    listaDeProdutos = doisX; // agora aponta para a nova area
    capacidadeMaxima = n; // claro...
    return; // e volta com o vetor novo
}

 

Não é? cria uma área com o dobro do tamanho, copia os caras, apaga a antiga e aponta para a nova.

 

Se a capacidade era 1, por exemplo, quando chega a hora...

 

Redimensionando: de 1 para 2
criada nova area
copiados produtos

 

E crie antes de tudo uma função para listar() porque é CLARO que vai precisar para poder testar...
 

void portfolio::listar()
{
    cout << quantidadeDeProdutos << " produtos na lista [max "
         << capacidadeMaxima << "]\n\n";
    for (int i = 0; i < quantidadeDeProdutos; i += 1)
        cout << i + 1 << ": " << listaDeProdutos[i].nome << "\n";
    cout << "    fim da lista\n\n";
}

 

faça seu programa trabalhar para você....

 

Assim ele já ostra o esperado ANTES de você perguntar: qual a capacidade? quantos tem? Quais os nomes?

 

4 produtos na lista [max 4]

1: n1
2: n2
3: n3
4: n4
    fim da lista

 

NUNCA escreva um programa interativo.

Se precisa ter um menu coloque depois.

não perca tempo com isso. Para testar com modestos 10 produtos vai mesmo ficar em frente ao terminal e digitar 30 campos? Por teste?

 

Use constantes ou funções factory que retornam produto. Use uma convenção para nomear as classes, como o clássico: reserva a primeira letra em maiúscula...

Link para o comentário
Compartilhar em outros sites

@arfneto o código que ele mandou foi o seguinte:

#include <iostream>
#include <vector> 
using namespace std;

struct produto {
    string nome;
    string marca;
    string descricao;
    produto();
};

produto::produto() {
    nome.clear();
    marca.clear();
    descricao.clear();
}

class portfolio {
    private:
        // *** AVISO: Não altere os atributos privados da classe *** 
        produto* listaDeProdutos;
        int quantidadeDeProdutos;
        int capacidadeMaxima;
    public:
        portfolio(int capacidade);
        ~portfolio();
        void inserirNovoProduto(const produto& umProduto);
        bool buscarProduto(const string& nome, produto& umProduto);
        void redimensionarCapacidade();
        friend void simularMudancaDeMarca(portfolio umPortfolio, string marcaAntiga, string novaMarca);
};

portfolio::portfolio(int capacidade) {
    quantidadeDeProdutos = 0;
    capacidadeMaxima = capacidade;
    listaDeProdutos = new produto[capacidadeMaxima];
}

portfolio::~portfolio() {
    delete [] listaDeProdutos;
}

void portfolio::inserirNovoProduto(const produto& umProduto) {
    if (quantidadeDeProdutos == capacidadeMaxima) { // vetor cheio, precisa redimensionar
        redimensionarCapacidade();
    }
    listaDeProdutos[quantidadeDeProdutos] = umProduto;
    quantidadeDeProdutos++;
}

bool portfolio::buscarProduto(const string& nomeParaBusca, produto& umProduto) {
    int posicaoAtual = 0;

    while (posicaoAtual < quantidadeDeProdutos and 
           listaDeProdutos[posicaoAtual].nome != nomeParaBusca) 
        posicaoAtual++;

    // se posicaoAtual não for menor que quantidade de produtos, é porque não encontrou
    if (posicaoAtual < quantidadeDeProdutos) {
        umProduto = listaDeProdutos[posicaoAtual];
        return true;
    }

    return false;
}

void portfolio::redimensionarCapacidade() {
#warning implemente este metodo!
}

void simularMudancaDeMarca(portfolio umPortfolio, string marcaAntiga, string novaMarca) {
    // *** AVISO: Não altere esta função *** 
    for (int i = 0; i < umPortfolio.quantidadeDeProdutos; i++) {
        if (umPortfolio.listaDeProdutos[i].marca == marcaAntiga) 
            cout << umPortfolio.listaDeProdutos[i].nome << " " << novaMarca << endl;
    }
    cout << endl;
}


int main() {
    // *** AVISO: Não altere a função principal, o main() *** 
    int capacidadeInicial;

    cout << "Produtos - Aplicativo para Controlar Portfolio\n" 
         << "Entre com capacidade máxima inicial: ";
    cin >> capacidadeInicial;

    portfolio meuPortfolio(capacidadeInicial);

    cout << "Portfolio - Escolha a Opção:\n"
         << "i - inserir novo produto\n"
         << "b - buscar por um dado produto a partir do nome\n"
         << "m - simular mudança de marca\n"
         << "s - para sair do programa" << endl;

    char opcaoDoMenu;
    produto umProduto;
    string nome;
    string marcaAntiga, marcaNova;

    cin >> opcaoDoMenu;

    while (opcaoDoMenu != 's') {
        switch(opcaoDoMenu) {
            case 'i' : 
                cout << "Entre com dados do produto (nome, marca, descrição):" << endl;
                cin >> umProduto.nome 
                    >> umProduto.marca
                    >> umProduto.descricao;
                meuPortfolio.inserirNovoProduto(umProduto);
                break;

            case 'b' :
                cout << "Entre com nome do produto para busca: ";
                cin >> nome;
                
                if (meuPortfolio.buscarProduto(nome, umProduto)) 
                    cout << umProduto.nome << " "
                         << umProduto.marca << " "
                         << umProduto.descricao << endl << endl;
                else 
                    cout << "Produto não encontrado!" << endl << endl;
                break;

            case 'm' : 
                cout << "Entre com marca antiga e atual: ";
                cin >> marcaAntiga >> marcaNova;
                simularMudancaDeMarca(meuPortfolio,marcaAntiga,marcaNova);
                break;

            case 's' : // não faz nada, espera retorno ao while para sair 
                break;

            default:
                cout << "Opção inválida!" << endl;
                break;

        }
        cout << "Portfolio - Escolha a Opção:\n"
             << "i - inserir novo produto\n"
             << "b - buscar por um dado produto a partir do nome\n"
             << "m - simular mudança de marca\n"
             << "s - para sair do programa" << endl;
        cin >> opcaoDoMenu;
    }

    return 0;
}

No caso a gente deveria completar a função void portfolio::redimensionarCapacidade() e resolver a falha de segmentação.

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

4 horas atrás, fevilela disse:

@codigo rápido tipo, quando eu coloco para mudar a marca e depois de mudar peço para procurar novamente ele fala que o produto não foi encontrado.

Mas ele tá lá, cadastrado? porque se for isso, então é mesmo o tamanho do seu array que tá errado.
Faz um print no momento que você cadastra pra tentar puxar e ver.

As vezes eu erro isso também. Pra arrumar isso talvez vai ter que colocar um "+1" ou "-1" em algum lugar...
usa breakpoint no final dos metodos (loops) que interagem com essa variavel. Ai você vai descobrir se tem que subtrair ou adicionar 1
 

Link para o comentário
Compartilhar em outros sites

@fevilela

3 horas atrás, fevilela disse:

sim, só não entendi a parte da função listar, porque no codigo tem a parte que fala que eu não posso alterar a class. E quando eu altero a marca e coloco para buscar novamente ele fala que o produto não foi encontrado

 

listar() é básico. Devia ter sido a primeira função que você escreveu, porque tem que ser capaz de listar uma lista vazia. 

Isso é para você, fazendo o seu programa trabalhar para você.

 

Algo assim:
 

            case 'i':
                cout << "Entre com dados do produto (nome, marca, "
                        "descrição):"
                     << endl;
                cin >> umProduto.nome >> umProduto.marca >>
                    umProduto.descricao;
                meuPortfolio.inserirNovoProduto(umProduto);
                meuPortfolio.listar();
                break;

 

Porque? 

 

Simples. depois de inserir lista. E responde aquela óbvia pergunta de quem está testando: inseriu ok?

 

E algo assim:

 

            case 'b':
                meuPortfolio.listar();
                cout << "Entre com nome do produto para busca: ";
                cin >> nome;

                if (meuPortfolio.buscarProduto(nome, umProduto))
                    cout << umProduto.nome << " " << umProduto.marca
                         << " " << umProduto.descricao << endl
                         << endl;
                else
                    cout << "Produto não encontrado!" << endl << endl;
                break;

 

Porque?

 

Simples. Antes de buscar lista os que tem lá. Assim você escolhe como testar.

 

Ao ficar confiante na implementação de cada opção você apaga essa chamada a listar().

 

Ao testar tudo você apaga a função listar() da classe. E seria a hora de então inserir o tal menu, como te expliquei. Escrevendo assim termina seu programa em poucas horas. E deve rodar certo logo no início.

 

 

De volta ao programa

 

Você recebeu um programa muito ruim. E mal escrito. Muitas vezes os instrutores fazem isso de propósito, de modo a depois mostrar algum conceito novo ou discutir problemas do próprio programa, e pode muito bem ser o caso desse. Em outros casos os instrutores são fracos mesmo, e espero que não seja esse o seu caso. Mas fique alerta ;) 

 

Por exemplo:

  • portfolio não tem um construtor padrão
  • produto() não tem o menor sentido, com aqueles string.clear();
  • incrementar um vetor em blocos de odo exponencial (quadrático nesse caso) é bobagem. Sempre se quer algo linear. E se busca muito por um valor inicial que atenda uma certa taxa de ocupação, para manter um mínimo de desperdício. Conforme a estrutura aumenta vai ficando cada vez mais i d i ota passar por exemplo de 500.000 para um milhão e manter essa memória alocada.
  • a tal simularxxx() é um if. Apenas lista os produtos de uma certa marca. que se pode aprender com isso?
  • redimensionarCapacidade() nunca seria um método da classe. Isso é uma função interna, de administração da estrutura.
  • Esses nomes gigantes para valores usados frequentemente são pouco produtivos. Uma atribuição como
        listaDeProdutos[quantidadeDeProdutos] = umProduto;
    não deveria ter mais de 50 colunas :)  
  • Esse código não tem sentido:
    void portfolio::redimensionarCapacidade()
    {
        //#warning implemente este metodo!
        std::vector<produto> listaDeProdutos;
        produto              umProduto;
        listaDeProdutos.erase(listaDeProdutos.begin() + 2);
        listaDeProdutos.push_back(umProduto);
    }

    se foi escrito de propósito deve ser um propósito bem oculto.

  • O tal menu deveria ser uma função

 

 

 

 

 

  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

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

Ebook grátis: Aprenda a ler resistores e capacitores!

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!