blloncoutz Posted July 21, 2012 at 07:32 PM Report #469563 Posted July 21, 2012 at 07:32 PM (edited) 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 July 21, 2012 at 07:33 PM by blloncoutz
pmg Posted July 21, 2012 at 08:18 PM Report #469576 Posted July 21, 2012 at 08:18 PM (edited) 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 July 21, 2012 at 08:18 PM 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!
blloncoutz Posted July 21, 2012 at 08:43 PM Author Report #469578 Posted July 21, 2012 at 08:43 PM 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?
pmg Posted July 21, 2012 at 08:55 PM Report #469580 Posted July 21, 2012 at 08:55 PM ... 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!
blloncoutz Posted July 21, 2012 at 09:41 PM Author Report #469593 Posted July 21, 2012 at 09:41 PM (edited) 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 July 21, 2012 at 09:42 PM by blloncoutz
pmg Posted July 21, 2012 at 10:13 PM Report #469598 Posted July 21, 2012 at 10:13 PM 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!
blloncoutz Posted July 21, 2012 at 11:30 PM Author Report #469602 Posted July 21, 2012 at 11:30 PM (edited) 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 July 21, 2012 at 11:31 PM by blloncoutz
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now