Ir para conteúdo
Fórum Script Brasil
  • 0

Problema com STL Lista


Diego_BM

Pergunta

Ola galera!

To com um problema na minha lista, que eu preciso inserir um assunto e um corpo de mensagem pra dentro da lista, problema que eu envio o objeto e quando eu crio um segundo assunto e corpo ele substitui o primeiro e adiciona o segundo....

por exemplo:

criei 1:

assunto: oi

corpo: bom dia

saida 1:

assunto:oi

corpo: bom dia

criei 2:

assunto: oi2

corpo: boa noite

(esta errado e acontece)

saida 2:

assunto: oi2

corpo: boa noite

assunto: oi2

corpo: boa noite

(esta certo e não acontece)

saida 2:

assunto: oi

corpo: boa dia

assunto: oi2

corpo: boa noite

O que eu posso fazer?

Codigo!

#include <iostream>
#include <list>
#include "Mensagem.h"
#include <fstream>

using std::ifstream;
using namespace std;

list<Mensagem> Lista;
list<Mensagem>::iterator  Lst;
list<Mensagem> Lista2;

int main(){
    char msg[50],ass[30];
    int opcao;
    opcao = 1;
    while(opcao!=6){
    Mensagem m;
    ifstream Mensagem("Mensagem.txt",ios::in);
    cout << "Escolha uma opcao: \n1 - Inserir Msg  \n2 - Remover Msg  \n3 - ordenalor por assunto \n4 - Mostrar Mensagens \n5 - juntar Filas \n6 - Sair" << endl;
    cin >> opcao;
    cin.get();
    switch(opcao){
        case 1:
            cout << "Digite um assunto: " << endl;
            cin.getline(ass, 30);
            cout <<  "Digite uma mensagem: " << endl;
            cin.getline(msg, 50);
            m.setAssunto(ass);
            m.setCorpo(msg);
            Lista.push_front(m);
            break;
Classe
#include "Mensagem.h"

Mensagem::Mensagem(void)
{
}

Mensagem::~Mensagem(void)
{
}
void Mensagem::setCorpo(char *c){
    corpo=c;
}
char* Mensagem::getCorpo(){
    return corpo;
}
void Mensagem::setAssunto(char *a){
    assunto=a;
}
char* Mensagem::getAssunto(){
    return assunto;

Editado por Diego_BM
Link para o comentário
Compartilhar em outros sites

16 respostass a esta questão

Posts Recomendados

  • 0

Evite utilizar getters e setters desnecessariamente. Ao invés de atributos privados (você não postou o .h, mas creio que tenha declarado corpo e assunto dessa forma) e getters/setters, você poderia ter deixado as propriedades públicas, ou mesmo utilizar uma struct.

ifstream Mensagem("Mensagem.txt",ios::in);
Não entendi direito o motivo do arquivo "mensagem.txt", então removi essa parte do código.
list<Mensagem> Lista;
list<Mensagem>::iterator  Lst;
As variáveis Lista e Lst estavam como variáveis globais. Alterei para que fossem locais à função main apenas para facilitar a organização.
Lista.push_from(m);
Troquei o push_front por push_back, para evitar que a lista seja mostrada na ordem inversa. Também modifiquei o código para, ao invés de utilizar vetores de caracteres, utilizar a classe std::string e acrescentei a parte de mostrar mensagens apenas para que pudesse testar. O código ficou assim:
#include <iostream>
#include <string>
#include <list>

using namespace std;

struct Mensagem{
    string
        assunto,
        corpo
;
};

int main(){
    list<Mensagem> Lista;
    list<Mensagem>::iterator  Lst;

    int opcao=1;
    while(opcao!=6){
        Mensagem m;
        cout << "Escolha uma opcao: \n1 - Inserir Msg  \n2 - Remover Msg  \n3 - ordenalor por assunto \n4 - Mostrar Mensagens \n5 - juntar Filas \n6 - Sair" << endl;
        cin >> opcao;
        cin.get();
        switch(opcao){
            case 1:
                cout << "Digite um assunto: " << endl;
                cin >> m.assunto;
                cout <<  "Digite uma mensagem: " << endl;
                cin >> m.corpo;
                Lista.push_back(m);
                break;
            case 4:
                unsigned int numero_mensagem=0;
                for(Lst=Lista.begin();Lst!=Lista.end();Lst++){
                    cout
                        << "Mensagem " << ++numero_mensagem << endl
                        << "\tAssunto: " << Lst->assunto << endl
                        << "\tMensagem: " << Lst->corpo << endl
        ;
                }
        }
    }
}

Qualquer dúvida posta aí.

Link para o comentário
Compartilhar em outros sites

  • 0

Tem um case que eu preciso do ifstream! mas não faz diferenca no meu erro.

Eu tenho um .h com set e get tanto de corpo como de assunto, eu não posso usar struct :/

.H

class Mensagem
{
private:
    char* assunto;
    char* corpo;
public:
    Mensagem(void);
    ~Mensagem(void);
    void setCorpo(char *c);
    char* getCorpo();
    void setAssunto(char *a);
    char* getAssunto();
    friend bool operator<(Mensagem &a, Mensagem &b){
        return (strcmp(a.getAssunto(),b.getAssunto())) < 0;
    }
};
.CPP
#include "Mensagem.h"

Mensagem::Mensagem(void)
{
}

Mensagem::~Mensagem(void)
{
}
void Mensagem::setCorpo(char *c){
    corpo=c;
}
char* Mensagem::getCorpo(){
    return corpo;
}
void Mensagem::setAssunto(char *a){
    assunto=a;
}
char* Mensagem::getAssunto(){
    return assunto;
}
MAIN
#include <iostream>
#include <list>
#include "Mensagem.h"
#include <fstream>

using std::ifstream;
using namespace std;

list<Mensagem> Lista;
list<Mensagem>::iterator  Lst;
list<Mensagem> Lista2;

int main(){
    char msg[50],ass[30];
    int opcao;
    opcao = 1;
    while(opcao!=6){
    Mensagem m;
    ifstream Mensagem("Mensagem.txt",ios::in);
    cout << "Escolha uma opcao: \n1 - Inserir Msg  \n2 - Remover Msg  \n3 - ordenalor por assunto \n4 - Mostrar Mensagens \n5 - juntar Filas \n6 - Sair" << endl;
    cin >> opcao;
    cin.get();
    switch(opcao){
        case 1:
            cout << "Digite um assunto: " << endl;
            cin.getline(ass, 30);
            cout <<  "Digite uma mensagem: " << endl;
            cin.getline(msg, 50);
            m.setAssunto(ass);
            m.setCorpo(msg);
            Lista.push_front(m);
            break;
        case 2:
            cout << "Digite o assunto para remover a mensagem" << endl;
            cin.getline(ass, 30);
            for(Lst=Lista.begin(); Lst!=Lista.end(); Lst++){
                while(!strcmp(ass,Lst->getAssunto())){
                    Lista.erase(Lst);
                }
            }
            break;
        case 3:
            Lista.sort();
            break;
        case 4:
            for(Lst=Lista.begin(); Lst!=Lista.end(); Lst++){
                cout << "Assunto: " << Lista.front().getAssunto() << endl;
                cout << "Mensagem: " << Lista.front().getCorpo() << endl;
            }
            break;
        case 5:
            char LinhaMsg[150];
            while(!Mensagem.eof()&& Mensagem!=NULL)
            {
                Mensagem.getline(LinhaMsg, 150);
                char *token;
                token = new char[strlen(LinhaMsg)];
                strcpy(token,LinhaMsg);
                strcpy(ass,strtok(token,";"));
                strcpy(msg,strtok(NULL, ";"));
                m.setAssunto(ass);
                m.setCorpo(msg);
                Lista2.push_front(m);
            }
            Mensagem.close();
            Lista.merge(Lista2);
        
            break;
        case 6:
        system("pause");
        break;
    }
    }
};

Acho que agora vai ficar mais intendivel pra vc!

garanto que é um erro bobo...

fica repetindo os dados inseridos :/

Link para o comentário
Compartilhar em outros sites

  • 0

Por que não pode utilizar struct ou mesmo deixar os atributos públicos?

De qualquer maneira, o problema é que você está sempre utilizando o mesmo vetor de caracteres (aquele declarado no início da função main) para gravar os dados. Uma solução é utilizar a alocação dinâmica para as strings ou mesmo a classe std::string.

A função main pode ficar assim:

int main(){
    char*ass,*msg;
    int opcao;
    opcao = 1;
    while(opcao!=6){
    Mensagem m;
    ifstream Mensagem("Mensagem.txt",ios::in);
    cout << "Escolha uma opcao: \n1 - Inserir Msg  \n2 - Remover Msg  \n3 - ordenalor por assunto \n4 - Mostrar Mensagens \n5 - juntar Filas \n6 - Sair" << endl;
    cin >> opcao;
    cin.get();
    switch(opcao){
        case 1:
            ass=(char*)malloc(30);
            msg=(char*)malloc(50);

            cout << "Digite um assunto: " << endl;
            cin.getline(ass, 30);
            cout <<  "Digite uma mensagem: " << endl;
            cin.getline(msg, 50);
            m.setAssunto(ass);
            m.setCorpo(msg);
            Lista.push_back(m);
            break;
        case 2:
            cout << "Digite o assunto para remover a mensagem" << endl;
            cin.getline(ass, 30);
            for(Lst=Lista.begin(); Lst!=Lista.end(); Lst++){
                while(!strcmp(ass,Lst->getAssunto())){
                    Lista.erase(Lst);
                }
            }
            break;
        case 3:
            Lista.sort();
            break;
        case 4:
            for(Lst=Lista.begin(); Lst!=Lista.end(); Lst++){
                cout << "Assunto: " << Lst->getAssunto() << endl;
                cout << "Mensagem: " << Lst->getCorpo() << endl;
            }
            break;
        case 5:
            char LinhaMsg[150];
            while(!Mensagem.eof()&& Mensagem!=NULL)
            {
                Mensagem.getline(LinhaMsg, 150);
                char *token;
                token = new char[strlen(LinhaMsg)];
                strcpy(token,LinhaMsg);
                strcpy(ass,strtok(token,";"));
                strcpy(msg,strtok(NULL, ";"));
                m.setAssunto(ass);
                m.setCorpo(msg);
                Lista2.push_front(m);
            }
            Mensagem.close();
            Lista.merge(Lista2);
        
            break;
        case 6:
        system("pause");
        break;
    }
    }
};

Link para o comentário
Compartilhar em outros sites

  • 0

Eu não posso usar por regra do professor, faco curso de seguranca da informacao, dai é tipo uma programacao segura....

cara vez de usar o malloc como eu faria isso com new?

Desculpe os erro de acento, teclado mt ruim =[

acho que eu entendi bem o erro agora! :D

Link para o comentário
Compartilhar em outros sites

  • 0

Sim, você também pode utilizar o new. O código ficaria assim:

ass=new char[30];
msg=new char[50];

Na minha opinião se uma variável pode ser modificada com setters ela pode se tornar pública. A única exceção é quando você precisa fazer algo no momento em que ela for alterada. Mas se seu professor quer assim, tudo bem.

Obs.:

Outra opção, ao invés de vetores de caracteres, é utilizar a classe std::string.

Link para o comentário
Compartilhar em outros sites

  • 0

Pelo pouco que eu entendo de programacao, pois estou comecando n faz mt tempo, se você colocar algo em private, uma injecao de SQL por exemplo fica mais dificil de ser implementada...

Esta dando um erro tipo isso!

cannot convert from 'char *' to 'char [50]'

eu tentei dar um new no objeto, ele compila, porem a execucao continua dando errado.

String não é mais dificil de ser manipulada que char* ?

Obrigado pela atencao!

Link para o comentário
Compartilhar em outros sites

  • 0

BOM!

Cara tu me deu uma luz e eu lembrei de uma coisa que eu ainda n tinha feito... hehehe

dentro do CPP da classe mensagem dei um new no dado que eu tava recebendo dai não da mais aquele erro.

debugei e deu tudo certinho na insercao, porem no mostrar os dados ainda ta dando errado, o problema agora ta no case 4 e não no case 1, hehe

a insercao ficou legal agora, problema é mostrar os dados =x

Resumindo debugando a insercao esta ok.O problema que mostrar os dados fica repetido. (case 4)

Problema aki:

for(Lst=Lista.begin(); Lst!=Lista.end(); Lst++){
                cout << "Assunto: " << Lista.back().getAssunto() << endl;
                cout << "Mensagem: " << Lista.back().getCorpo() << endl;
            }
MAIN
#include <iostream>
#include <list>
#include "Mensagem.h"
#include <fstream>

using std::ifstream;
using namespace std;

list<Mensagem> Lista;
list<Mensagem>::iterator  Lst;
list<Mensagem> Lista2;

int main(){
    char msg[50],ass[30];
    int opcao;
    opcao = 1;
    while(opcao!=6){
    Mensagem m;
    ifstream Msg("Mensagem.txt",ios::in);
    cout << "Escolha uma opcao: \n1 - Inserir Msg  \n2 - Remover Msg  \n3 - ordenalor por assunto \n4 - Mostrar Mensagens \n5 - juntar Filas \n6 - Sair" << endl;
    cin >> opcao;
    cin.get();
    switch(opcao){
        case 1:
            cout << "Digite um assunto: " << endl;
            cin.getline(ass, 30);
            cout <<  "Digite uma mensagem: " << endl;
            cin.getline(msg, 50);
            //m = new Mensagem();
            m.setAssunto(ass);
            m.setCorpo(msg);
            Lista.push_front(m);
            break;
        case 2:
            cout << "Digite o assunto para remover a mensagem" << endl;
            cin.getline(ass, 30);
            for(Lst=Lista.begin(); Lst!=Lista.end(); Lst++){
                while(!strcmp(ass,Lst->getAssunto())){
                    Lista.erase(Lst);
                }
            }
            break;
        case 3:
            Lista.sort();
            break;
        case 4:
            for(Lst=Lista.begin(); Lst!=Lista.end(); Lst++){
                cout << "Assunto: " << Lista.back().getAssunto() << endl;
                cout << "Mensagem: " << Lista.back().getCorpo() << endl;
            }
            break;
        case 5:
            char LinhaMsg[150];
            while(!Msg.eof()&& Msg!=NULL)
            {
                Msg.getline(LinhaMsg, 150);
                char *token;
                token = new char[strlen(LinhaMsg)];
                strcpy(token,LinhaMsg);
                strcpy(ass,strtok(token,";"));
                strcpy(msg,strtok(NULL, ";"));
                m.setAssunto(ass);
                m.setCorpo(msg);
                Lista2.push_front(m);
            }
            Msg.close();
            Lista.merge(Lista2);
        
            break;
        case 6:
        system("pause");
        break;
    }
    }
};
.H
#pragma once
#include <iostream>

class Mensagem
{
private:
    char* assunto;
    char* corpo;
public:
    Mensagem(void);
    ~Mensagem(void);
    void setCorpo(char *c);
    char* getCorpo();
    void setAssunto(char *a);
    char* getAssunto();
    friend bool operator<(Mensagem &a, Mensagem &b){
        return (strcmp(a.getAssunto(),b.getAssunto())) < 0;
    }
};
.CPP
#include "Mensagem.h"

Mensagem::Mensagem(void)
{
}

Mensagem::~Mensagem(void)
{
}

void Mensagem::setCorpo(char *c){
    corpo = new char[strlen(c)]; //arrumado
    strcpy(corpo,c); //arrumado
}
char* Mensagem::getCorpo(){
    return corpo;
}
void Mensagem::setAssunto(char *a){
    assunto = new char[strlen(a)]; //arrumado
    strcpy(assunto,a); //arrumado
}
char* Mensagem::getAssunto(){
    return assunto;
}

Link para o comentário
Compartilhar em outros sites

  • 0

Sim, abri o forum pra responder! isso mesmo que eu fiz! hehehe

so falta uma coisinha agora e esta pronto =]

Problema no case 2! =[

Serve pra deletar uma mensagem por assunto, problema que eu percebi que ele se confunde e erra na incrementacao :/

Mensagem de erro de execucao" list iterator incompatible"

cout << "Digite o assunto para remover a mensagem" << endl;
            cin.getline(ass, 30);
            for(Lst!=Lista.begin();Lst!=Lista.end(); Lst++){
                if(!strcmp(ass,Lst->getAssunto())){
                    Lista.erase(Lst);
                }
            }

Editado por Diego_BM
Link para o comentário
Compartilhar em outros sites

  • 0

O código os seguintes problemas:

  • Você ainda está utilizando push_front ao invés de push_back para inserir as mensagens (isso não é um erro, mas a ordem vai ficar invertida)
  • O código que você postou no #post 11 não está utilizando alocação dinâmica.
  • Você não alocou memória para o assunto, ou seja, a variável ainda apontava para o assunto da última mensagem inserida.
  • Você não estava parando o loop após remover o item desejado da lista.
Em relação aos primeiros 2 problemas, acho que foi porque você postou o código errado.

O código da função main pode ficar assim:

int main(){
    char *msg,*ass;
    int opcao;
    opcao = 1;
    while(opcao!=6){
    Mensagem m;
    ifstream Msg("Mensagem.txt",ios::in);
    cout << "Escolha uma opcao: \n1 - Inserir Msg  \n2 - Remover Msg  \n3 - ordenalor por assunto \n4 - Mostrar Mensagens \n5 - juntar Filas \n6 - Sair" << endl;
    cin >> opcao;
    cin.get();
    switch(opcao){
        case 1:
            ass=new char[30];
            msg=new char[50];
            cout << "Digite um assunto: " << endl;
            cin.getline(ass, 30);
            cout <<  "Digite uma mensagem: " << endl;
            cin.getline(msg, 50);
            //m = new Mensagem();
            m.setAssunto(ass);
            m.setCorpo(msg);
            Lista.push_back(m);
            break;
        case 2:
            cout << "Digite o assunto para remover a mensagem" << endl;
            ass=new char[30];
            cin.getline(ass, 30);
            for(Lst=Lista.begin(); Lst!=Lista.end(); Lst++){
                if(!strcmp(ass,Lst->getAssunto())){
                    Lista.erase(Lst);
                    break;
                }
            }
            delete[] ass; //limpa a memória
            break;
        case 3:
            Lista.sort();
            break;
        case 4:
            for(Lst=Lista.begin(); Lst!=Lista.end(); Lst++){
                cout << "Assunto: " << Lst->getAssunto() << endl;
                cout << "Mensagem: " << Lst->getCorpo() << endl;
            }
            break;
        case 5:
            char LinhaMsg[150];
            while(!Msg.eof()&& Msg!=NULL)
            {
                Msg.getline(LinhaMsg, 150);
                char *token;
                token = new char[strlen(LinhaMsg)];
                strcpy(token,LinhaMsg);
                strcpy(ass,strtok(token,";"));
                strcpy(msg,strtok(NULL, ";"));
                m.setAssunto(ass);
                m.setCorpo(msg);
                Lista2.push_front(m);
            }
            Msg.close();
            Lista.merge(Lista2);
        
            break;
        case 6:
        system("pause");
        break;
    }
    }
};

Link para o comentário
Compartilhar em outros sites

  • 0

Amigo acho que voce esta se confundindo um pouco, então vou exclarecer os topicos que voce colocou.

- Tanto faz no meo codigo usar push_front ou push_back

- O codigo do post 11 esta usando alocacao dinamica não para o objeto, mas sim para os capos corpo e assunto(arquivo CPP)

- A alocacao de memoria que eu fiz para os campos esta no CPP, então cada vez que eu acessae o metodo ele vai alocar memoria, vez de ter q colocar new toda vez q usar assunto ou o corpo no main.

- Eu coloquei o break no case 2 assim como você fez e não deu certo, na verdade aquilo não é um loop, ele vai parar de ver se o assunto que eu digitei é igual ao assunto que tem na lista quando encontrar o final da lista, so que se eu tirar um ele se perde na contagem ali no caso é o Lst++

Link para o comentário
Compartilhar em outros sites

  • 0
- Tanto faz no meo codigo usar push_front ou push_back
Sim, tanto faz, mas não faz muito sentido exibir os dados para o usuário na ordem inversa à que ele cadastrou.

- O codigo do post 11 esta usando alocacao dinamica não para o objeto, mas sim para os capos corpo e assunto(arquivo CPP)
Desculpe, realmente não tinha visto essa modificação.

- Eu coloquei o break no case 2 assim como você fez e não deu certo, na verdade aquilo não é um loop, ele vai parar de ver se o assunto que eu digitei é igual ao assunto que tem na lista quando encontrar o final da lista, so que se eu tirar um ele se perde na contagem ali no caso é o Lst++

Na verdade é um loop sim, e o objetivo de usar o break é justamente evitar que ele tente continuar a contagem e se perca.

O problema é que seu código estava utilizando um while ao invés de um if para comparar os assuntos, o que não faz muito sentido. Dessa forma, o break apenas parava o for mais interno, e não o for para percorrer os assuntos. Troque:

for(Lst=Lista.begin(); Lst!=Lista.end(); Lst++){
    while(!strcmp(ass,Lst->getAssunto())){
        Lista.erase(Lst);
        break;
    }
}
Por:
for(Lst=Lista.begin(); Lst!=Lista.end(); Lst++){
    if(!strcmp(ass,Lst->getAssunto())){
        Lista.erase(Lst);
        break;
    }
}

Obs.:

Seu código ainda estava usando List.back(), alterei novamente para Lst.

Link para o comentário
Compartilhar em outros sites

Participe da discussão

Você pode postar agora e se registrar depois. Se você já tem uma conta, acesse agora para postar com sua conta.

Visitante
Responder esta pergunta...

×   Você colou conteúdo com formatação.   Remover formatação

  Apenas 75 emoticons são permitidos.

×   Seu link foi incorporado automaticamente.   Exibir como um link em vez disso

×   Seu conteúdo anterior foi restaurado.   Limpar Editor

×   Você não pode colar imagens diretamente. Carregar ou inserir imagens do URL.



  • Estatísticas dos Fóruns

    • Tópicos
      152,3k
    • Posts
      652,4k
×
×
  • Criar Novo...