Jump to content
blloncoutz

Lista Ligada: como limitar a inserção de dados

Recommended Posts

blloncoutz

Boas.

Estou a desenvolver um programa que regista empréstimos de livros.

Até agora quando inseria um empréstimo novo, dentro da estrutura de dados dos empréstimos, os dados que colocava eram os que me apetecia.

Eis a estrutura:

typedef struct emprestimo{
		 char nome[51];
		 char isbn[18];
		 data data_req;

		 data data_ent;
		 int prazo;
		 }
ficha_emprestimo;

typedef struct _no_emprestimo{
		 ficha_emprestimo emp;
		 struct _no_emprestimo *next;
   }no_emprestimo;

A nova problemática é a seguinte:

O Programa deverá passar a gerir uma lista ligada de utilizadores com os campos Nome e BI/CC.

Os empréstimos deverão passar a estar associados a esta nova funcionalidade, só os utilizadores desta lista poderão fazer empréstimos, ou seja, só os nomes introduzidos no campo Nome da lista ligada de utilizadores poderão ser introduzidos no campo Nome da lista ligada dos Empréstimos.

Eis a abordagem de inserção dos dois casos:

Empréstimos:

no_emprestimo *AdicionaEmprestimo(no_emprestimo *plistaemp)
   {


		 no_emprestimo *aux;

		 ficha_emprestimo e;
		 int temp;
		 _int64 rawtime;
		 struct tm *r,*d;
		 int classe;
		 if(!(aux=(no_emprestimo *)malloc(sizeof(no_emprestimo)))){
				printf("Erro na reserva de memória");
				exit(1);
		 }

		 puts("\n***** Insira os dados de emprestimo *****\n");



				printf("Nome do Requisitante:"); // este nome passa a estar limitado pela lista ligada de utilizadores
				fflush(stdin);
				gets(e.nome);
				puts("ISBN:***-*-**-******-* : ");
				gets(e.isbn);
  printf("Prazo:%d\n",e.prazo);	  


		 aux->emp=e;
		 aux->next=plistaemp;

   return aux;
   }

Utilizadores:

typedef struct socio{
		 char nome[51];
		 char bi[10];

		 }
ficha_socio;
typedef struct _no_socio{
		 ficha_socio socio;
		 struct _no_socio *seg;
   }no_socio;
ficha_socio InserirSocio()
{
ficha_socio s;
printf("Introduza o nome do Sócio");
gets(s.nome);
printf("Introduza o Bi + nºcontrolo");
gets(s.bi);
return s;
no_socio *AdicionaSocio(no_socio *inicio)
{
 no_socio *aux,*plista=inicio,*ant=inicio;
 if(!(aux=(no_socio *)malloc(sizeof(no_socio))))
 {
  printf("Erro na reserva de memoria");
  exit(1);
 }
 aux->socio=InserirSocio();
 while(plista!=NULL && strcmp(aux->socio.nome,plista->socio.nome)>0)
 {
  ant=plista;
  plista=plista->seg;
 }
 if(ant==plista)
  inicio=aux;
 else
  ant->seg=aux;
  aux->seg=plista;
return inicio;
}

Como limitar nos empréstimos, apenas o nomes que estão na lista ligada dos utilizadores para a inserção, visto que, com esta abordagem só poderei retornar um valor e pela minha lógica se fizesse assim, não daria, penso eu:

no_emprestimo *AdicionaEmprestimo(no_emprestimo *plistaemp,no_socio *plista)
   {


		 no_emprestimo *aux;
		 ficha_emprestimo e;
		 int temp;
		 _int64 rawtime;
		 struct tm *r,*d;
		 int classe;
		 if(!(aux=(no_emprestimo *)malloc(sizeof(no_emprestimo)))){
				printf("Erro na reserva de memória");
				exit(1);
		 }

		 puts("\n***** Insira os dados de emprestimo *****\n");


	   while(strcmp(plista->socio.nome,e.nome))
		{
				printf("Nome do Requisitante:"); // este nome passa a estar limitado pela lista ligada de utilizadores
				fflush(stdin);
				gets(e.nome);
plista=plista->seg;
	  }

Se esta abordagem está pouco correcta, gostaria que me ajudassem.

Agradecido.

Edited by blloncoutz

Share this post


Link to post
Share on other sites
pmg

Uma solucao passa pela alteracao da estrutura do emprestimo: em vez dum char[] para o nome, passas a ter um ponteiro para um socio

struct socio { /* ... */ };
struct emprestimo {
 struct socio *utilizador;
 /* ... */
};

Edited by pmg

What have you tried?

Não respondo a dúvidas por PM

A minha bola de cristal está para compor; deve ficar pronta para a semana.

Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!

Share this post


Link to post
Share on other sites
blloncoutz

Uma solucao passa pela alteracao da estrutura do emprestimo: em vez dum char[] para o nome, passas a ter um ponteiro para um socio

struct socio { /* ... */ };
struct emprestimo {
 struct socio *utilizador;
 /* ... */
};

e depois como fazer a condição na introdução?

Share this post


Link to post
Share on other sites
pmg
... fflush(stdin) ...
... gets ...

Xiiii ... nem tinha visto isto.

O fflush(stdin) nao esta definido pelo Standard. Usando fflush num stream de input limitas a funcionalidade do teu programa desnecessariamente.

O gets() é impossivel de ser usado com seguranca. Nao o uses nem para programetas de exemplo ou teste!

e depois como fazer a condição na introdução?

Verificas se o nome faz parte da lista, retornando um ponteiro para o socio em questao (ou NULL caso nao faca parte da lista). Se o resultado da pesquisa for NULL, nao inseres ... se for um ponteiro para um socio, inseres com esse ponteiro.


What have you tried?

Não respondo a dúvidas por PM

A minha bola de cristal está para compor; deve ficar pronta para a semana.

Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!

Share this post


Link to post
Share on other sites
blloncoutz

Xiiii ... nem tinha visto isto.

O fflush(stdin) nao esta definido pelo Standard. Usando fflush num stream de input limitas a funcionalidade do teu programa desnecessariamente.

O gets() é impossivel de ser usado com seguranca. Nao o uses nem para programetas de exemplo ou teste!

Verificas se o nome faz parte da lista, retornando um ponteiro para o socio em questao (ou NULL caso nao faca parte da lista). Se o resultado da pesquisa for NULL, nao inseres ... se for um ponteiro para um socio, inseres com esse ponteiro.

então qual a proposta para usar em vez do gets()?

Será que me podia exemplificar com código é que assim não entendi muito bem.

Edited by blloncoutz

Share this post


Link to post
Share on other sites
pmg

então qual a proposta para usar em vez do gets()?

Usa o fgets() e, se necessario, remove o ENTER final tal e qual como o gets() faz.

#include <stdio.h>

   char buffer[100];
   // gets(buffer);
   fgets(buffer, sizeof buffer, stdin);
   size_t blen = strlen(buffer);
   if (buffer[blen - 1] == '\n') buffer[--len] = 0; /* apaga o ENTER  e actualiza blen */

Nota que a diferenca entre o fgets() e o gets() e que o fgets() nunca vai escrever para alem do tamanho do buffer, e gets() escreve ate ao ENTER inclusive (mais um '\0'). Se o utilizador escrever uma linha com 100 caracteres e o ENTER no #101 o gets() vai escrever 102 bytes no buffer (que so tem espaco para 100!!); o fgets() escreve 99 bytes da linha do utilizador mais o '\0', ficando o byte #100 e o ENTER (#101) "pendurados" ate uma proxima leitura.

Para ignorar esse byte #100 e o ENTER, podes verificar o ultimo byte e apagar o ENTER como em cima ou, caso nao haja ENTER, ignorar o resto da linha (deitando fora coisas que o utilizador escreveu)

fgets(buffer, sizeof buffer, stdin);
blen = strlen(buffer);
if (buffer[blen - 1] == '\n') {
 /* linha completa, apagar o ENTER e actualizar blen */
 buffer[--blen] = 0;
} else {
 /* linha incompleta, ignorar o resto do input ate um ENTER ou EOF */
 int ch;
 while (((ch = getchar()) != '\n') && (ch != EOF)) /* void */;
}

Nota que o compeimento do buffer nunca sera 0 assumindo que o stdin esteja a apontar para um ficheiro de texto. Se for possivel estares a ler dados binarios esta abordagem esta errada: nesse caso deves usar fread().


What have you tried?

Não respondo a dúvidas por PM

A minha bola de cristal está para compor; deve ficar pronta para a semana.

Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!

Share this post


Link to post
Share on other sites
blloncoutz

Usa o fgets() e, se necessario, remove o ENTER final tal e qual como o gets() faz.

#include <stdio.h>

char buffer[100];
// gets(buffer);
fgets(buffer, sizeof buffer, stdin);
size_t blen = strlen(buffer);
if (buffer[blen - 1] == '\n') buffer[--len] = 0; /* apaga o ENTER  e actualiza blen */

Nota que a diferenca entre o fgets() e o gets() e que o fgets() nunca vai escrever para alem do tamanho do buffer, e gets() escreve ate ao ENTER inclusive (mais um '\0'). Se o utilizador escrever uma linha com 100 caracteres e o ENTER no #101 o gets() vai escrever 102 bytes no buffer (que so tem espaco para 100!!); o fgets() escreve 99 bytes da linha do utilizador mais o '\0', ficando o byte #100 e o ENTER (#101) "pendurados" ate uma proxima leitura.

Para ignorar esse byte #100 e o ENTER, podes verificar o ultimo byte e apagar o ENTER como em cima ou, caso nao haja ENTER, ignorar o resto da linha (deitando fora coisas que o utilizador escreveu)

fgets(buffer, sizeof buffer, stdin);
blen = strlen(buffer);
if (buffer[blen - 1] == '\n') {
 /* linha completa, apagar o ENTER e actualizar blen */
 buffer[--blen] = 0;
} else {
 /* linha incompleta, ignorar o resto do input ate um ENTER ou EOF */
 int ch;
 while (((ch = getchar()) != '\n') && (ch != EOF)) /* void */;
}

Nota que o compeimento do buffer nunca sera 0 assumindo que o stdin esteja a apontar para um ficheiro de texto. Se for possivel estares a ler dados binarios esta abordagem esta errada: nesse caso deves usar fread().

Referia-me à abordagem de só aceitar nomes da lista de ligada dos sócios introduzidos, para introduzir um novo empréstimo à lista ligada emprestimos.

foi isso que não entendi.

eis o que tentei fazer:

typedef struct date{
		 int dia, mes, ano;}
data;

typedef struct socio{
		 char nome[51];
		 char bi[12];

		 }
ficha_socio;
typedef struct _no_socio{
		 ficha_socio socio;
		 struct _no_socio *seg;
   }no_socio;
typedef struct emprestimo{
		 ficha_socio nome;// é aqui que faço isto? e depois como abordar o problema na inserção de empréstimos?
		 char isbn[18];
		 data data_req;

		 data data_ent;
		 int prazo;
		 }
ficha_emprestimo;

typedef struct _no_emprestimo{
		 ficha_emprestimo emp;
		 struct _no_emprestimo *next;
   }no_emprestimo;

(...)



no_emprestimo *AdicionaEmprestimo(no_emprestimo *plistaemp)
   {



		 char nome[100];
		 ficha_emprestimo e;

		 if(!(aux=(no_emprestimo *)malloc(sizeof(no_emprestimo)))){
				printf("Erro na reserva de memória");
				exit(1);
		 }

			   do{
				printf("Nome do Requisitante:");
				fflush(stdin);
				gets(nome);
				plistaemp=plistaemp->next;
				}while(strcmp(nome,e.nome.nome));


            aux->emp=e;
            aux->next=plistaemp;

}





só me falta mesmo isto para completar o programa.

Só aceitar nomes da lista ligada socios para introduzir um novo empréstimo.

Mais uma vez obrigado.

Edited by blloncoutz

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.