Ir ao conteúdo
  • Cadastre-se

Problema ao usar ponteiros numa string em uma lista encadeada.


Kleber Lauton
Ir à solução Resolvido por Edmorte,

Posts recomendados

Boa tarde.

Meu código está quase funcionando 100%, só há um problema.

 

Tenho que cadastrar varias informações de alguns livros em uma struct e depois passá-las para uma lista duplamente encadeada (estou deixando só algumas variáveis para ficar menos bagunçado).

 

 

O PROBLEMA: Consigo inserir valores na lista e imprimi-los. Mas só consigo fazer isto com números e char (apenas uma letra). Quando tento inserir na lista uma string com 2 letras ou mais sem os ponteiros ele me retorna apenas a primeira letra.

 

ENTRADA

obra: Divindade

RETORNO

obra: D

 

Pelo que eu li, devo usar ponteiros NO CHAR para inserir quantos caracteres eu quiser, mas sinceramente não consigo. Eu ainda não domino o uso de ponteiros muito bem, achei o código da lista pronto e modifiquei para meu código.

#define n 2     //numero de livrosusing namespace std;struct livros{	int codigo[n];	char doacao[n]; 		// s/n	char *obra[n];	char autor[n];};struct Tipo_Lista{   int cod;   char doacao;   	char *obra;	char autor;	   struct Tipo_Lista *Prox;   struct Tipo_Lista *Ant;};struct Tipo_Lista *Primeiro;struct Tipo_Lista *Ultimo;void FLVazia(){            //cria lista vazia     struct Tipo_Lista *aux;     aux = (struct Tipo_Lista*)malloc(sizeof(struct Tipo_Lista));     Primeiro = aux;     Ultimo = Primeiro;     Primeiro->Ant = NULL;}

Como vocês viram acima, tentei utilizar um ponteiro em "obra", e neste código abaixo também (que é o valor b ) . 

void Insere(int x,char a, char *b, char c){       //inserir valores    	struct Tipo_Lista *aux;    	aux = (struct Tipo_Lista*)malloc(sizeof(struct Tipo_Lista));		aux->cod = x;    	aux->doacao = a;    	aux->obra = b;    	aux->autor = c;     Ultimo->Prox = aux;     aux->Ant = Ultimo;     Ultimo = Ultimo->Prox;     aux->Prox = NULL;}void Imprime(){               //imprime valores  struct Tipo_Lista *aux;  aux = Primeiro->Prox;  while(aux !=NULL){    cout << "\nCod = " << aux->cod;    cout << "\nDoa = " << aux->doacao;    cout << "\nObra = " << aux->obra;    cout << "\nAutor = " << aux->autor;    aux = aux->Prox;  }}

Aqui na main, todos os dados da estrutura ''livros'' já estão armazenados em. x.codigo, x.doacao,x.obra... Após ter todos os dados, eu os insiro para a lista com esse laço for e tenho meu retorno com a função Imprime.

livros x;   int codigo,i;        FLVazia();  			 								for (i=0;i<n;i++){			Insere(x.codigo[i],x.doacao[i],x.obra[i],x.autor[i]);	}	 	Imprime();

Só preciso conseguir passar dados de string, int e char de uma struct para uma lista duplamente encadeada. Alguém pode me mostrar como colocar os ponteiros corretamente ou se tem modo mais fácil? 

 

Código completo:

#include <cstdlib>#include <iostream>#include <string.h>#include <windows.h>#include <conio.h>#include <string>#define n 1using namespace std;struct livros{	int codigo[n];	char doacao[n]; 		// s/n	char obra[n];	char autor[n];	char editora[n];	int area[n]; 			//1 - exatas, 2 - humanas, 3 - biológicas	char key1[n];	char key2[n];	char key3[n];};struct Tipo_Lista{   int cod;   char doacao;   	char obra;	char autor;	char editora;	int area; 				char key1;	char key2;	char key3;	   struct Tipo_Lista *Prox;   struct Tipo_Lista *Ant;};struct Tipo_Lista *Primeiro;struct Tipo_Lista *Ultimo;void FLVazia(){     struct Tipo_Lista *aux;     aux = (struct Tipo_Lista*)malloc(sizeof(struct Tipo_Lista));     Primeiro = aux;     Ultimo = Primeiro;     Primeiro->Ant = NULL;}void Insere(int x,char a,char b,char c,char d,int e,char f,char g, char h){    	struct Tipo_Lista *aux;    	aux = (struct Tipo_Lista*)malloc(sizeof(struct Tipo_Lista));		aux->cod = x;    	aux->doacao = a;    	aux->obra = b;    	aux->autor = c;        aux->editora = d;        aux->area = e;        aux->key1 = f;        aux->key2 = g;        aux->key3 = h;     Ultimo->Prox = aux;     aux->Ant = Ultimo;     Ultimo = Ultimo->Prox;     aux->Prox = NULL;}void Imprime(){  struct Tipo_Lista *aux;  aux = Primeiro->Prox;  while(aux !=NULL){    cout << "\nCod = " << aux->cod;    cout << "\nDoa = " << aux->doacao;    cout << "\nObra = " << aux->obra;    cout << "\nAutor = " << aux->autor;    cout << "\nEditora = " << aux->editora;    cout << "\nArea = " << aux->area;    cout << "\nKey1 = " << aux->key1;    cout << "\nKey2 = " << aux->key3;	cout << "\nKey3 = " << aux->key3;  aux = aux->Prox;  }}void quick(int v[], int esquerda, int direita){    int i, j, x, y;							// y é auxiliar    i = esquerda;    j = direita;    x = v[(esquerda + direita) / 2];      // O "x" também é chamado de "pivo"     while(i <= j)    {        while(v[i] < x && i < direita){            i++;        }        while(v[j] > x && j > esquerda){            j--;        }        if(i <= j){            y = v[i];            v[i] = v[j];            v[j] = y;            i++;            j--;        			}    }    if(j > esquerda){        quick(v, esquerda, j);    }    if(i < direita){        quick(v,  i, direita);    }            }int main(int argc, char *argv[]){	livros x;   	int codigo,i;										//le os códigos dos livros e organiza  	for (i=0;i<n;i++){  		cout << "--------- Livro " << i+1 << " ---------\n";    	cout <<"\nEntre com o codigo da obra: ";    	cin >> x.codigo[i];    	cout << endl;    }    	quick(x.codigo,0,n-1);   	 // v (vetor), 0 (início do vetor), fim (tamanho do vetor -1)    for (i=0;i<n;i++){			  		cout << "\nUTILIZE PONTOS EM VEZ DE ESPACO PARA SEPARAR AS PALAVRAS!\nExemplo: o.dia.em.que.a.terra.parou\n\n";    	cout << "--------- Livro " << i+1 << " ---------\n";		cout <<"\nA obra e uma doacao? <s> SIM <n> NAO: ";    	cin >> x.doacao[i];   		cout <<"\nQual o nome da obra?: ";    	cin >> x.obra[i];    	cout <<"\nInsira o nome do autor: ";    	cin >> x.autor[i];    	cout <<"\nDigite o nome da editora: ";    	cin >> x.editora[i];    	cout <<"\nQual a area do livro? <1> EXATAS <2> HUMANAS <3> BIOLOGICAS: ";    	cin >> x.area[i];    	cout <<"\nDigite a 1a palavra chave da obra: ";    	cin >> x.key1[i];    	cout <<"\nDigite a 2a palavra chave da obra: ";    	cin >> x.key2[i];    	cout <<"\nDigite a 3a palavra chave da obra: ";    	cin >> x.key3[i];		cout << "\n";	}	FLVazia();  			 //inicia pilha vazia							//inseri na pilha todos os dados	for (i=0;i<n;i++){			Insere(x.codigo[i],x.doacao[i],x.obra[i],x.autor[i],x.editora[i],x.area[i],x.key1[i],x.key2[i],x.key3[i]);  	}	   	Imprime();  /*    		for (i=0;i<n;i++){   	cout << endl << "codigo " << i <<" = " <<  x.codigo[i];    	cout << endl << "doacao " << i <<" = " <<  x.doacao[i];    	cout << endl << x.obra[i];    	cout << endl << x.autor[i];    	cout << endl << x.editora[i];    	cout << endl << x.area[i];    	cout << endl << x.key1[i];    	cout << endl << x.key2[i];    	cout << endl << x.key3[i];		}   */   	    //  getch();	cout << "\n\n";	system("pause");	return 0;} 

Link para o comentário
Compartilhar em outros sites

Man não vou analisar seu código porque você parece saber o que está fazendo, mas seu problema parece ser entender como funcionam as strings em C. Então vou te dar uma aula express.

 

No C não existe o conceito de string, logo em C nós usamos o conceito de cadeia de char para simbolizar uma string.

 

Logo precisamos avisar ao compilador quanto espaço reservar para a tal string e colocar o '\0' no final para ele saber que ela já acabou, senão problemas surgem. Não se preocupe com o '\0' a não ser que esteja fazendo manipulações manuais, todas as funções de biblioteca que começam com str sabem tratá-lo.

 

Então no C para ler um nome você precisa primeiro declarar e definir seu espaço, não vou aqui esgotar suas opções, vamos usar a mais simples delas:

char nome[10]; // Declara um nome com 9 espaços, porque 1 deles é para '\0' (fim de string).

Depois que você tem essa cadeia declarada, existe um recurso no compilador que é o fato de todo ARRAY poder ser tratado como um PONTEIRO.

 

Logo você pode passar nome como parâmetro para uma função e na função declarar como char* ptr_nome.

 

Quando você declara char* ptr_nome você está apenas declarando um ponteiro, ele será usado para manipular alguma memória, ele por si só não aloca nenhuma memória para você, ele é apenas um manipulador. O compilador permite que você use esse ponteiro com a mesma sintaxe de ARRAY.

void xpto(char* ptr_nome){    ptr_nome[0]; // Sintaxe de array em ponteiro para facilitar a vida do programador.}

A declaração:

char* arrayDePonteiros[10]; // Você está criando um array de 10 ponteiros char.

Não é o que você quer fazer.

 

Com isso você deve ser capaz de arrumar o seu código.

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

Cara, obrigado mesmo! Só precisei utilizar "char *obra[n];" tanto na struct quanto na lista.

Descobri que precisaria usar o malloc. Deste jeito eu consigo usar a quantidade que eu quiser.

x.obra[i] = (char *) malloc(sizeof(60));cin >> x.obra[i]; 

Funciona perfeitamente quando cadastro as informações de um livro na struct.

 

Mas quando minha struct tem 2 livros ou mais, o programa trava na hora de cadastrar. Há 6 variáveis que uso o malloc igual ao exemplo acima. Eu preciso esvaziar a memória alocada toda vez que eu utilizar o malloc?

Link para o comentário
Compartilhar em outros sites

  • Solução

Cara, obrigado mesmo! Só precisei utilizar "char *obra[n];" tanto na struct quanto na lista.

Descobri que precisaria usar o malloc. Deste jeito eu consigo usar a quantidade que eu quiser.

x.obra[i] = (char *) malloc(sizeof(60));cin >> x.obra[i]; 

Funciona perfeitamente quando cadastro as informações de um livro na struct.

 

Mas quando minha struct tem 2 livros ou mais, o programa trava na hora de cadastrar. Há 6 variáveis que uso o malloc igual ao exemplo acima. Eu preciso esvaziar a memória alocada toda vez que eu utilizar o malloc?

 

Sim, todo malloc tem um free associado a ele, por isso eu prefiro C++, posso encapsular a alocação dentro da classe e desalocar com RAII no destrutor. Mas todo malloc tem que ser liberado com free, senão você cria um memory leak.

 

Esse uso que você fez é o que eu disse que não ia explorar, você deixou de usar o escopo automático que aloca o espaço na Stack e desaloca ao fim do bloco e usou o escopo dinâmico, aonde você pede memória do Heap e é responsável por devolver ela para o Sistema Operacional.

 

Eu voltaria para o uso da Stack para casos mais simples. Você pode criar uma matriz char.

 

Exemplo: char obras[n][20]. N obras de nome (tamanho máximo 19, tem sempre uma posição para fim de string).

 

Se você usar malloc vai ter que gerenciar o tempo de vida para liberar quando para de usar, deixe para usar esse recurso quando você tiver mais experiencia.

Link para o comentário
Compartilhar em outros sites

Visitante
Este tópico está impedido de receber novas respostas.

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